Merge branch 'MDL-32657-master-1' of git://git.luns.net.uk/moodle
[moodle.git] / lib / form / filemanager.js
blob915fe90627bd5072b76f85de1697ff7eaca36435
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15 /**
16  *
17  * File Manager UI
18  * =====
19  * this.api, stores the URL to make ajax request
20  * this.currentpath
21  * this.filepicker_options
22  * this.movefile_dialog
23  * this.mkdir_dialog
24  * this.rename_dialog
25  * this.client_id
26  * this.filecount, how many files in this filemanager
27  * this.maxfiles
28  * this.maxbytes
29  *
30  * FileManager options:
31  * =====
32  * this.options.currentpath
33  * this.options.itemid
34  */
37 M.form_filemanager = {};
39 /**
40  * This fucntion is called for each file picker on page.
41  */
42 M.form_filemanager.init = function(Y, options) {
43     var FileManagerHelper = function(options) {
44         FileManagerHelper.superclass.constructor.apply(this, arguments);
45     };
46     FileManagerHelper.NAME = "FileManager";
47     FileManagerHelper.ATTRS = {
48         options: {},
49         lang: {}
50     };
52     Y.extend(FileManagerHelper, Y.Base, {
53         api: M.cfg.wwwroot+'/repository/draftfiles_ajax.php',
54         menus: {},
55         initializer: function(options) {
56             this.options = options;
57             if (options.mainfile) {
58                 this.enablemainfile = options.mainfile;
59             }
60             this.client_id = options.client_id;
61             this.currentpath = '/';
62             this.maxfiles = options.maxfiles;
63             this.maxbytes = options.maxbytes;
64             this.emptycallback = null; // Used by drag and drop upload
66             this.filepicker_options = options.filepicker?options.filepicker:{};
67             this.filepicker_options.client_id = this.client_id;
68             this.filepicker_options.context = options.context;
69             this.filepicker_options.maxfiles = this.maxfiles;
70             this.filepicker_options.maxbytes = this.maxbytes;
71             this.filepicker_options.env = 'filemanager';
72             this.filepicker_options.itemid = options.itemid;
74             if (options.filecount) {
75                 this.filecount = options.filecount;
76             } else {
77                 this.filecount = 0;
78             }
79             this.setup_buttons();
80             this.refresh(this.currentpath); // MDL-31113 get latest list from server
81         },
83         wait: function(client_id) {
84             var container = Y.one('#filemanager-'+client_id);
85             container.set('innerHTML', '');
86             var html = Y.Node.create('<ul id="draftfiles-'+client_id+'"></ul>');
87             container.appendChild(html);
88             var panel = Y.one('#draftfiles-'+client_id);
89             var name = '';
90             var str = '<div style="text-align:center">';
91             str += '<img src="'+M.util.image_url('i/loading_small')+'" />';
92             str += '</div>';
93             try {
94                 panel.set('innerHTML', str);
95             } catch(e) {
96                 alert(e.toString());
97             }
98         },
99         request: function(args, redraw) {
100             var api = this.api + '?action='+args.action;
101             var params = {};
102             var scope = this;
103             if (args['scope']) {
104                 scope = args['scope'];
105             }
106             params['sesskey'] = M.cfg.sesskey;
107             params['client_id'] = this.client_id;
108             params['filepath'] = this.currentpath;
109             params['itemid'] = this.options.itemid?this.options.itemid:0;
110             if (args['params']) {
111                 for (i in args['params']) {
112                     params[i] = args['params'][i];
113                 }
114             }
115             var cfg = {
116                 method: 'POST',
117                 on: {
118                     complete: function(id,o,p) {
119                         if (!o) {
120                             alert('IO FATAL');
121                             return;
122                         }
123                         var data = Y.JSON.parse(o.responseText);
124                         args.callback(id,data,p);
125                     }
126                 },
127                 arguments: {
128                     scope: scope
129                 },
130                 headers: {
131                     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
132                     'User-Agent': 'MoodleFileManager/3.0'
133                 },
134                 data: build_querystring(params)
135             };
136             if (args.form) {
137                 cfg.form = args.form;
138             }
139             Y.io(api, cfg);
140             if (redraw) {
141                 this.wait(this.client_id);
142             }
143         },
144         filepicker_callback: function(obj) {
145             this.filecount++;
146             this.check_buttons();
147             this.refresh(this.currentpath);
148             if (typeof M.core_formchangechecker != 'undefined') {
149                 M.core_formchangechecker.set_form_changed();
150             }
151         },
152         check_buttons: function() {
153             var button_addfile  = Y.one("#btnadd-"+this.client_id);
154             if (this.filecount > 0) {
155                 Y.one("#btndwn-"+this.client_id).setStyle('display', 'inline');
156             }
157             if (this.filecount >= this.maxfiles && this.maxfiles!=-1) {
158                 button_addfile.setStyle('display', 'none');
159             }
160         },
161         refresh: function(filepath) {
162             var scope = this;
163             this.currentpath = filepath;
164             if (!filepath) {
165                 filepath = this.currentpath;
166             } else {
167                 this.currentpath = filepath;
168             }
169             this.request({
170                 action: 'list',
171                 scope: scope,
172                 params: {'filepath':filepath},
173                 callback: function(id, obj, args) {
174                     scope.filecount = obj.filecount;
175                     scope.check_buttons();
176                     scope.options = obj;
177                     scope.render(obj);
178                 }
179             }, true);
180         },
181         setup_buttons: function() {
182             var button_download = Y.one("#btndwn-"+this.client_id);
183             var button_create   = Y.one("#btncrt-"+this.client_id);
184             var button_addfile  = Y.one("#btnadd-"+this.client_id);
186             // setup 'add file' button
187             // if maxfiles == -1, the no limit
188             if (this.filecount >= this.maxfiles
189                     && this.maxfiles!=-1) {
190                 button_addfile.setStyle('display', 'none');
191             } else {
192                 button_addfile.on('click', function(e) {
193                     var options = this.filepicker_options;
194                     options.formcallback = this.filepicker_callback;
195                     // XXX: magic here, to let filepicker use filemanager scope
196                     options.magicscope = this;
197                     options.savepath = this.currentpath;
198                     M.core_filepicker.show(Y, options);
199                 }, this);
200             }
202             // setup 'make a folder' button
203             if (this.options.subdirs) {
204                 button_create.on('click',function(e) {
205                     var scope = this;
206                     // a function used to perform an ajax request
207                     function perform_action(e) {
208                         var foldername = Y.one('#fm-newname').get('value');
209                         if (!foldername) {
210                             return;
211                         }
212                         scope.request({
213                             action:'mkdir',
214                             params: {filepath:scope.currentpath, newdirname:foldername},
215                             callback: function(id, obj, args) {
216                                 var filepath = obj.filepath;
217                                 scope.mkdir_dialog.hide();
218                                 scope.refresh(filepath);
219                                 Y.one('#fm-newname').set('value', '');
220                                 if (typeof M.core_formchangechecker != 'undefined') {
221                                     M.core_formchangechecker.set_form_changed();
222                                 }
223                             }
224                         });
225                     }
226                     if (!Y.one('#fm-mkdir-dlg')) {
227                         var dialog = Y.Node.create('<div id="fm-mkdir-dlg"><div class="hd">'+M.str.repository.entername+'</div><div class="bd"><input type="text" id="fm-newname" /></div></div>');
228                         Y.one(document.body).appendChild(dialog);
229                         this.mkdir_dialog = new YAHOO.widget.Dialog("fm-mkdir-dlg", {
230                              width: "300px",
231                              visible: true,
232                              x:e.pageX,
233                              y:e.pageY,
234                              constraintoviewport : true
235                              });
237                     }
238                     var buttons = [ { text:M.str.moodle.ok, handler:perform_action, isDefault:true },
239                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
241                     this.mkdir_dialog.cfg.queueProperty("buttons", buttons);
242                     this.mkdir_dialog.render();
243                     this.mkdir_dialog.show();
244                 }, this);
245             } else {
246                 button_create.setStyle('display', 'none');
247             }
249             // setup 'download this folder' button
250             // NOTE: popup window must be enabled to perform download process
251             button_download.on('click',function() {
252                 var scope = this;
253                 // perform downloaddir ajax request
254                 this.request({
255                     action: 'downloaddir',
256                     scope: scope,
257                     callback: function(id, obj, args) {
258                         if (obj) {
259                             scope.refresh(obj.filepath);
260                             var win = window.open(obj.fileurl, 'fm-download-folder');
261                             if (!win) {
262                                 alert(M.str.repository.popupblockeddownload);
263                             }
264                         } else {
265                             alert(M.str.repository.draftareanofiles);
266                         }
267                     }
268                 });
269             }, this);
270         },
271         empty_filelist: function(container) {
272             var content = '<div class="mdl-align">'+M.str.repository.nofilesattached;
273             content += '<span id="dndenabled2-'+this.client_id+'" style="display: none">';
274             content += ' - '+M.util.get_string('dndenabled_inbox', 'moodle')+'</span>';
275             content += '</div>';
276             content += this.upload_message();
277             container.set('innerHTML', content);
278             if (this.emptycallback) {
279                 this.emptycallback(this.client_id);
280             }
281         },
282         upload_message: function() {
283             var div = '<div id="filemanager-uploadmessage'+this.client_id+'" style="display:none" class="dndupload-target">';
284             div += M.util.get_string('droptoupload', 'moodle');
285             div += '</div>';
286             return div;
287         },
288         render: function() {
289             var options = this.options;
290             var path = this.options.path;
291             var list = this.options.list;
292             var breadcrumb = Y.one('#fm-path-'+this.client_id);
293             // build breadcrumb
294             if (path) {
295                 // empty breadcrumb
296                 breadcrumb.set('innerHTML', '');
297                 var count = 0;
298                 for(var p in path) {
299                     var arrow = '';
300                     if (count==0) {
301                         arrow = Y.Node.create('<span>'+M.str.moodle.path + ': </span>');
302                     } else {
303                         arrow = Y.Node.create('<span> â–¶ </span>');
304                     }
305                     count++;
307                     var pathid  = 'fm-path-node-'+this.client_id;
308                     pathid += ('-'+count);
310                     var crumb = Y.Node.create('<a href="###" id="'+pathid+'">'+path[p].name+'</a>');
311                     breadcrumb.appendChild(arrow);
312                     breadcrumb.appendChild(crumb);
314                     var args = {};
315                     args.requestpath = path[p].path;
316                     args.client_id = this.client_id;
317                     Y.one('#'+pathid).on('click', function(e, args) {
318                         var scope = this;
319                         var params = {};
320                         params['filepath'] = args.requestpath;
321                         this.currentpath = args.requestpath;
322                         this.request({
323                             action: 'list',
324                             scope: scope,
325                             params: params,
326                             callback: function(id, obj, args) {
327                                 scope.filecount = obj.filecount;
328                                 scope.check_buttons();
329                                 scope.options = obj;
330                                 scope.render(obj);
331                             }
332                         }, true);
333                     }, this, args);
334                 }
335             }
336             var template = Y.one('#fm-template');
337             var container = Y.one('#filemanager-' + this.client_id);
338             var listhtml = '';
340             // folder list items
341             var folder_ids = [];
342             var folder_data = {};
344             // normal file list items
345             var file_ids   = [];
346             var file_data  = {};
348             // archives list items
349             var zip_ids    = [];
350             var zip_data = {};
352             var html_ids = [];
353             var html_data = {};
355             file_data.itemid = folder_data.itemid = zip_data.itemid = options.itemid;
356             file_data.client_id = folder_data.client_id = zip_data.client_id = this.client_id;
358             var foldername_ids = [];
359             if (!list || list.length == 0) {
360                 // hide file browser and breadcrumb
361                 //container.setStyle('display', 'none');
362                 this.empty_filelist(container);
363                 if (!path || path.length <= 1) {
364                     breadcrumb.setStyle('display', 'none');
365                 }
366                 return;
367             } else {
368                 container.setStyle('display', 'block');
369                 breadcrumb.setStyle('display', 'block');
370             }
372             var count = 0;
373             for(var i in list) {
374                 count++;
375                 // the li html element
376                 var htmlid = 'fileitem-'+this.client_id+'-'+count;
377                 // link to file
378                 var fileid = 'filename-'+this.client_id+'-'+count;
379                 // file menu
380                 var action = 'action-'  +this.client_id+'-'+count;
382                 var html = template.get('innerHTML');
384                 html_ids.push('#'+htmlid);
385                 html_data[htmlid] = action;
387                 list[i].htmlid = htmlid;
388                 list[i].fileid = fileid;
389                 list[i].action = action;
391                 var url = "###";
393                 switch (list[i].type) {
394                     case 'folder':
395                         // click folder name
396                         foldername_ids.push('#'+fileid);
397                         // click folder menu
398                         folder_ids.push('#'+action);
399                         folder_data[action] = list[i];
400                         folder_data[fileid] = list[i];
401                         break;
402                     case 'file':
403                         file_ids.push('#'+action);
404                         // click file name
405                         file_ids.push('#'+fileid);
406                         file_data[action] = list[i];
407                         file_data[fileid] = list[i];
408                         if (list[i].url) {
409                             url = list[i].url;
410                         }
411                     break;
412                     case 'zip':
413                         zip_ids.push('#'+action);
414                         zip_ids.push('#'+fileid);
415                         zip_data[action] = list[i];
416                         zip_data[fileid] = list[i];
417                         if (list[i].url) {
418                             url = list[i].url;
419                         }
420                     break;
421                 }
422                 var fullname = list[i].fullname;
424                 if (list[i].sortorder == 1) {
425                     html = html.replace('___fullname___', '<strong><a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a></strong>');
426                 } else {
427                     html = html.replace('___fullname___', '<a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a>');
428                 }
429                 html = html.replace('___action___', '<span class="fm-menuicon" id="'+action+'"><img alt="â–¶" src="'+M.util.image_url('i/menu')+'" /></span>');
430                 html = '<li id="'+htmlid+'">'+html+'</li>';
431                 listhtml += html;
432             }
433             if (!Y.one('#draftfiles-'+this.client_id)) {
434                 var filelist = Y.Node.create('<ul id="draftfiles-'+this.client_id+'"></ul>');
435                 container.appendChild(filelist);
436             }
437             listhtml += this.upload_message();
438             Y.one('#draftfiles-'+this.client_id).set('innerHTML', listhtml);
440             // click normal file menu
441             Y.on('click', this.create_filemenu, file_ids, this, file_data);
442             Y.on('contextmenu', this.create_filemenu, file_ids, this, file_data);
443             // click folder menu
444             Y.on('click', this.create_foldermenu, folder_ids, this, folder_data);
445             Y.on('contextmenu', this.create_foldermenu, folder_ids, this, folder_data);
446             Y.on('contextmenu', this.create_foldermenu, foldername_ids, this, folder_data);
447             // click archievs menu
448             Y.on('click', this.create_zipmenu, zip_ids, this, zip_data);
449             Y.on('contextmenu', this.create_zipmenu, zip_ids, this, zip_data);
450             // click folder name
451             Y.on('click', this.enter_folder, foldername_ids, this, folder_data);
452         },
453         enter_folder: function(e, data) {
454             var node = e.currentTarget;
455             var file = data[node.get('id')];
456             this.refresh(file.filepath);
457         },
458         create_filemenu: function(e, data) {
459             e.preventDefault();
460             var options = this.options;
461             var node = e.currentTarget;
462             var file = data[node.get('id')];
463             var scope = this;
465             var menuitems = [
466                 {text: M.str.moodle.download, onclick:{fn:open_file_in_new_window, obj:file, scope:this}}
467                 ];
468             function setmainfile(type, ev, obj) {
469                 var file = obj[node.get('id')];
470                 //Y.one(mainid).set('value', file.filepath+file.filename);
471                 var params = {};
472                 params['filepath']   = file.filepath;
473                 params['filename']   = file.filename;
474                 this.request({
475                     action: 'setmainfile',
476                     scope: scope,
477                     params: params,
478                     callback: function(id, obj, args) {
479                         scope.refresh(scope.currentpath);
480                     }
481                 });
482             }
483             function open_file_in_new_window(type, ev, obj) {
484                 // We open in a new window rather than changing the current windows URL as we don't
485                 // want to navigate away from the page
486                 window.open(obj.url, 'fm-download-file');
487             }
488             if (this.enablemainfile && (file.sortorder != 1)) {
489                 var mainid = '#id_'+this.enablemainfile;
490                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
491                 menuitems.push(menu);
492             }
493             this.create_menu(e, 'filemenu', menuitems, file, data);
494         },
495         create_foldermenu: function(e, data) {
496             e.preventDefault();
497             var scope = this;
498             var node = e.currentTarget;
499             var fileinfo = data[node.get('id')];
500             // an extra menu item for folder to zip it
501             function archive_folder(type,ev,obj) {
502                 var params = {};
503                 params['filepath']   = fileinfo.filepath;
504                 params['filename']   = '.';
505                 this.request({
506                     action: 'zip',
507                     scope: scope,
508                     params: params,
509                     callback: function(id, obj, args) {
510                         scope.refresh(obj.filepath);
511                     }
512                 });
513             }
514             var menuitems = [
515                 {text: M.str.editor.zip, onclick: {fn: archive_folder, obj: data, scope: this}},
516                 ];
517             this.create_menu(e, 'foldermenu', menuitems, fileinfo, data);
518         },
519         create_zipmenu: function(e, data) {
520             e.preventDefault();
521             var scope = this;
522             var node = e.currentTarget;
523             var fileinfo = data[node.get('id')];
525             function unzip(type, ev, obj) {
526                 var params = {};
527                 params['filepath'] = fileinfo.filepath;
528                 params['filename'] = fileinfo.fullname;
529                 this.request({
530                     action: 'unzip',
531                     scope: scope,
532                     params: params,
533                     callback: function(id, obj, args) {
534                         scope.refresh(obj.filepath);
535                     }
536                 });
537             }
538             var menuitems = [
539                 {text: M.str.moodle.download, url:fileinfo.url},
540                 {text: M.str.moodle.unzip, onclick: {fn: unzip, obj: data, scope: this}}
541                 ];
542             function setmainfile(type, ev, obj) {
543                 var file = obj[node.get('id')];
544                 //Y.one(mainid).set('value', file.filepath+file.filename);
545                 var params = {};
546                 params['filepath']   = file.filepath;
547                 params['filename']   = file.filename;
548                 this.request({
549                     action: 'setmainfile',
550                     scope: scope,
551                     params: params,
552                     callback: function(id, obj, args) {
553                         scope.refresh(scope.currentpath);
554                     }
555                 });
556             }
557             if (this.enablemainfile && (fileinfo.sortorder != 1)) {
558                 var mainid = '#id_'+this.enablemainfile;
559                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
560                 menuitems.push(menu);
561             }
562             this.create_menu(e, 'zipmenu', menuitems, fileinfo, data);
563         },
564         create_menu: function(ev, menuid, menuitems, fileinfo, options) {
565             var position = [ev.pageX, ev.pageY];
566             var scope = this;
567             function remove(type, ev, obj) {
568                 var dialog_options = {};
569                 var params = {};
570                 dialog_options.message = M.str.repository.confirmdeletefile;
571                 dialog_options.scope = this;
572                 var filename = '';
573                 var filepath = '';
574                 if (fileinfo.type == 'folder') {
575                     params.filename = '.';
576                     params.filepath = fileinfo.filepath;
577                 } else {
578                     params.filename = fileinfo.fullname;
579                 }
580                 dialog_options.callbackargs = [params];
581                 dialog_options.callback = function(params) {
582                     this.request({
583                         action: 'delete',
584                         scope: this,
585                         params: params,
586                         callback: function(id, obj, args) {
587                             scope.filecount--;
588                             scope.refresh(obj.filepath);
589                             if (typeof M.core_formchangechecker != 'undefined') {
590                                 M.core_formchangechecker.set_form_changed();
591                             }
592                             if (scope.filecount < scope.maxfiles && scope.maxfiles!=-1) {
593                                 var button_addfile  = Y.one("#btnadd-"+scope.client_id);
594                                 button_addfile.setStyle('display', 'inline');
595                                 button_addfile.on('click', function(e) {
596                                     var options = scope.filepicker_options;
597                                     options.formcallback = scope.filepicker_callback;
598                                     // XXX: magic here, to let filepicker use filemanager scope
599                                     options.magicscope = scope;
600                                     options.savepath = scope.currentpath;
601                                     M.core_filepicker.show(Y, options);
602                                 }, this);
603                             }
604                         }
605                     });
606                 };
607                 M.util.show_confirm_dialog(ev, dialog_options);
608             }
609             function rename (type, ev, obj) {
610                 var scope = this;
611                 var perform = function(e) {
612                     var newfilename = Y.one('#fm-rename-input').get('value');
613                     if (!newfilename) {
614                         return;
615                     }
617                     var action = '';
618                     var params = {};
619                     if (fileinfo.type == 'folder') {
620                         params['filepath']   = fileinfo.filepath;
621                         params['filename']   = '.';
622                         params['newdirname'] = newfilename;
623                         action = 'renamedir';
624                     } else {
625                         params['filepath']   = fileinfo.filepath;
626                         params['filename']   = fileinfo.fullname;
627                         params['newfilename'] = newfilename;
628                         action = 'rename';
629                     }
630                     scope.request({
631                         action: action,
632                         scope: scope,
633                         params: params,
634                         callback: function(id, obj, args) {
635                             if (obj == false) {
636                                 alert(M.str.repository.fileexists);
637                             } else {
638                                 scope.refresh(obj.filepath);
639                                 if (typeof M.core_formchangechecker != 'undefined') {
640                                     M.core_formchangechecker.set_form_changed();
641                                 }
642                             }
643                             Y.one('#fm-rename-input').set('value', '');
644                             scope.rename_dialog.hide();
645                         }
646                     });
647                 };
649                 var dialog = Y.one('#fm-rename-dlg');
650                 if (!dialog) {
651                     dialog = Y.Node.create('<div id="fm-rename-dlg"><div class="hd">'+M.str.repository.enternewname+'</div><div class="bd"><input type="text" id="fm-rename-input" /></div></div>');
652                     Y.one(document.body).appendChild(dialog);
653                     this.rename_dialog = new YAHOO.widget.Dialog("fm-rename-dlg", {
654                          width: "300px",
655                          fixedcenter: true,
656                          visible: true,
657                          constraintoviewport : true
658                          });
660                 }
661                 var buttons = [ { text:M.str.moodle.rename, handler:perform, isDefault:true},
662                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
664                 this.rename_dialog.cfg.queueProperty('buttons', buttons);
665                 this.rename_dialog.render();
666                 this.rename_dialog.show();
667                 //var k1 = new YAHOO.util.KeyListener(scope, {keys:13}, {fn:function(){perform();}, correctScope: true});
668                 //k1.enable();
669                 Y.one('#fm-rename-input').set('value', fileinfo.fullname);
670             }
671             function move(type, ev, obj) {
672                 var scope = this;
673                 var itemid = this.options.itemid;
674                 // setup move file dialog
675                 var dialog = null;
676                 if (!Y.one('#fm-move-dlg')) {
677                     dialog = Y.Node.create('<div id="fm-move-dlg"></div>');
678                     Y.one(document.body).appendChild(dialog);
679                 } else {
680                     dialog = Y.one('#fm-move-dlg');
681                 }
683                 dialog.set('innerHTML', '<div class="hd">'+M.str.repository.moving+'</div><div class="bd"><div id="fm-move-div">'+M.str.repository.nopathselected+'</div><div id="fm-tree"></div></div>');
685                 this.movefile_dialog = new YAHOO.widget.Dialog("fm-move-dlg", {
686                      width : "600px",
687                      fixedcenter : true,
688                      visible : false,
689                      constraintoviewport : true
690                      });
692                 var treeview = new YAHOO.widget.TreeView("fm-tree");
694                 var dialog = this.movefile_dialog;
695                 function _move(e) {
696                     if (!treeview.targetpath) {
697                         return;
698                     }
699                     var params = {};
700                     if (fileinfo.type == 'folder') {
701                         action = 'movedir';
702                     } else {
703                         action = 'movefile';
704                     }
705                     params['filepath'] = fileinfo.filepath;
706                     params['filename'] = fileinfo.fullname;
707                     params['newfilepath'] = treeview.targetpath;
708                     scope.request({
709                         action: action,
710                         scope: scope,
711                         params: params,
712                         callback: function(id, obj, args) {
713                             var p = '/';
714                             if (obj) {
715                                 p = obj.filepath;
716                             }
717                             dialog.cancel();
718                             scope.refresh(p);
719                             if (typeof M.core_formchangechecker != 'undefined') {
720                                 M.core_formchangechecker.set_form_changed();
721                             }
722                         }
723                     });
724                 }
726                 var buttons = [ { text:M.str.moodle.move, handler:_move, isDefault:true },
727                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
729                 this.movefile_dialog.cfg.queueProperty("buttons", buttons);
730                 this.movefile_dialog.render();
732                 treeview.subscribe("dblClickEvent", function(e) {
733                     // update destidatoin folder
734                     this.targetpath = e.node.data.path;
735                     var title = Y.one('#fm-move-div');
736                     title.set('innerHTML', '<strong>"' + this.targetpath + '"</strong> has been selected.');
737                 });
739                 function loadDataForNode(node, onCompleteCallback) {
740                     var params = {};
741                     params['filepath'] = node.data.path;
742                     var obj = {
743                         action: 'dir',
744                         scope: scope,
745                         params: params,
746                         callback: function(id, obj, args) {
747                             data = obj.children;
748                             if (data.length == 0) {
749                                 // so it is empty
750                             } else {
751                                 for (var i in data) {
752                                     var textnode = {label: data[i].fullname, path: data[i].filepath, itemid: this.itemid};
753                                     var tmpNode = new YAHOO.widget.TextNode(textnode, node, false);
754                                 }
755                             }
756                             this.oncomplete();
757                         }
758                     };
759                     obj.oncomplete = onCompleteCallback;
760                     scope.request(obj);
761                 }
763                 this.movefile_dialog.subscribe('show', function(){
764                     var rootNode = treeview.getRoot();
765                     treeview.setDynamicLoad(loadDataForNode);
766                     treeview.removeChildren(rootNode);
767                     var textnode = {label: M.str.moodle.files, path: '/'};
768                     var tmpNode = new YAHOO.widget.TextNode(textnode, rootNode, true);
769                     treeview.draw();
770                 }, this, true);
772                 this.movefile_dialog.show();
773             }
774             var shared_items = [
775                 {text: M.str.moodle.rename+'...', onclick: {fn: rename, obj: options, scope: this}},
776                 {text: M.str.moodle.move+'...', onclick: {fn: move, obj: options, scope: this}}
777             ];
778             // delete is reserve word in Javascript
779             shared_items.push({text: M.str.moodle['delete']+'...', onclick: {fn: remove, obj: options, scope: this}});
780             var menu = new YAHOO.widget.Menu(menuid, {xy:position, clicktohide:true});
781             menu.clearContent();
782             menu.addItems(menuitems);
783             menu.addItems(shared_items);
784             menu.render(document.body);
785             menu.subscribe('hide', function(){
786                 this.fireEvent('destroy');
787             });
788             menu.show();
789         }
790     });
792     // finally init everything needed
793     // kill nonjs filemanager
794     var item = document.getElementById('nonjs-filemanager-'+options.client_id);
795     if (item && !options.usenonjs) {
796         item.parentNode.removeChild(item);
797     }
798     // hide loading picture
799     item = document.getElementById('filemanager-loading-'+options.client_id);
800     if (item) {
801         item.parentNode.removeChild(item);
802     }
803     // display filemanager interface
804     item = document.getElementById('filemanager-wrapper-'+options.client_id);
805     if (item) {
806         item.style.display = '';
807     }
809     var manager = new FileManagerHelper(options);
810     var dndoptions = {
811         filemanager: manager,
812         acceptedtypes: options.accepted_types,
813         clientid: options.client_id,
814         maxfiles: options.maxfiles,
815         maxbytes: options.maxbytes,
816         itemid: options.itemid,
817         repositories: manager.filepicker_options.repositories,
818         containerprefix: '#filemanager-',
819     };
820     M.form_dndupload.init(Y, dndoptions);