de89ff33ff878f4d175586a3fa6b55cccf4bd2fc
[moodle.git] / lib / form / filemanager.js
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.
12 //
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;
65             this.filepicker_options = options.filepicker?options.filepicker:{};
66             this.filepicker_options.client_id = this.client_id;
67             this.filepicker_options.context = options.context;
68             this.filepicker_options.maxfiles = this.maxfiles;
69             this.filepicker_options.maxbytes = this.maxbytes;
70             this.filepicker_options.env = 'filemanager';
71             this.filepicker_options.itemid = options.itemid;
73             if (options.filecount) {
74                 this.filecount = options.filecount;
75             } else {
76                 this.filecount = 0;
77             }
78             this.setup_buttons();
79             this.refresh(this.currentpath); // MDL-31113 get latest list from server
80         },
82         wait: function(client_id) {
83             var container = Y.one('#filemanager-'+client_id);
84             container.set('innerHTML', '');
85             var html = Y.Node.create('<ul id="draftfiles-'+client_id+'"></ul>');
86             container.appendChild(html);
87             var panel = Y.one('#draftfiles-'+client_id);
88             var name = '';
89             var str = '<div style="text-align:center">';
90             str += '<img src="'+M.util.image_url('i/loading_small')+'" />';
91             str += '</div>';
92             try {
93                 panel.set('innerHTML', str);
94             } catch(e) {
95                 alert(e.toString());
96             }
97         },
98         request: function(args, redraw) {
99             var api = this.api + '?action='+args.action;
100             var params = {};
101             var scope = this;
102             if (args['scope']) {
103                 scope = args['scope'];
104             }
105             params['sesskey'] = M.cfg.sesskey;
106             params['client_id'] = this.client_id;
107             params['filepath'] = this.currentpath;
108             params['itemid'] = this.options.itemid?this.options.itemid:0;
109             if (args['params']) {
110                 for (i in args['params']) {
111                     params[i] = args['params'][i];
112                 }
113             }
114             var cfg = {
115                 method: 'POST',
116                 on: {
117                     complete: function(id,o,p) {
118                         if (!o) {
119                             alert('IO FATAL');
120                             return;
121                         }
122                         var data = Y.JSON.parse(o.responseText);
123                         args.callback(id,data,p);
124                     }
125                 },
126                 arguments: {
127                     scope: scope
128                 },
129                 headers: {
130                     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
131                     'User-Agent': 'MoodleFileManager/3.0'
132                 },
133                 data: build_querystring(params)
134             };
135             if (args.form) {
136                 cfg.form = args.form;
137             }
138             Y.io(api, cfg);
139             if (redraw) {
140                 this.wait(this.client_id);
141             }
142         },
143         filepicker_callback: function(obj) {
144             this.filecount++;
145             this.check_buttons();
146             this.refresh(this.currentpath);
147             M.util.set_form_changed();
148         },
149         check_buttons: function() {
150             var button_addfile  = Y.one("#btnadd-"+this.client_id);
151             if (this.filecount > 0) {
152                 Y.one("#btndwn-"+this.client_id).setStyle('display', 'inline');
153             }
154             if (this.filecount >= this.maxfiles && this.maxfiles!=-1) {
155                 button_addfile.setStyle('display', 'none');
156             }
157         },
158         refresh: function(filepath) {
159             var scope = this;
160             this.currentpath = filepath;
161             if (!filepath) {
162                 filepath = this.currentpath;
163             } else {
164                 this.currentpath = filepath;
165             }
166             this.request({
167                 action: 'list',
168                 scope: scope,
169                 params: {'filepath':filepath},
170                 callback: function(id, obj, args) {
171                     scope.filecount = obj.filecount;
172                     scope.check_buttons();
173                     scope.options = obj;
174                     scope.render(obj);
175                 }
176             }, true);
177         },
178         setup_buttons: function() {
179             var button_download = Y.one("#btndwn-"+this.client_id);
180             var button_create   = Y.one("#btncrt-"+this.client_id);
181             var button_addfile  = Y.one("#btnadd-"+this.client_id);
183             // setup 'add file' button
184             // if maxfiles == -1, the no limit
185             if (this.filecount >= this.maxfiles
186                     && this.maxfiles!=-1) {
187                 button_addfile.setStyle('display', 'none');
188             } else {
189                 button_addfile.on('click', function(e) {
190                     var options = this.filepicker_options;
191                     options.formcallback = this.filepicker_callback;
192                     // XXX: magic here, to let filepicker use filemanager scope
193                     options.magicscope = this;
194                     options.savepath = this.currentpath;
195                     M.core_filepicker.show(Y, options);
196                 }, this);
197             }
199             // setup 'make a folder' button
200             if (this.options.subdirs) {
201                 button_create.on('click',function(e) {
202                     var scope = this;
203                     // a function used to perform an ajax request
204                     function perform_action(e) {
205                         var foldername = Y.one('#fm-newname').get('value');
206                         if (!foldername) {
207                             return;
208                         }
209                         scope.request({
210                             action:'mkdir',
211                             params: {filepath:scope.currentpath, newdirname:foldername},
212                             callback: function(id, obj, args) {
213                                 var filepath = obj.filepath;
214                                 scope.mkdir_dialog.hide();
215                                 scope.refresh(filepath);
216                                 Y.one('#fm-newname').set('value', '');
217                                 M.util.set_form_changed();
218                             }
219                         });
220                     }
221                     if (!Y.one('#fm-mkdir-dlg')) {
222                         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>');
223                         Y.one(document.body).appendChild(dialog);
224                         this.mkdir_dialog = new YAHOO.widget.Dialog("fm-mkdir-dlg", {
225                              width: "300px",
226                              visible: true,
227                              x:e.pageX,
228                              y:e.pageY,
229                              constraintoviewport : true
230                              });
232                     }
233                     var buttons = [ { text:M.str.moodle.ok, handler:perform_action, isDefault:true },
234                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
236                     this.mkdir_dialog.cfg.queueProperty("buttons", buttons);
237                     this.mkdir_dialog.render();
238                     this.mkdir_dialog.show();
239                 }, this);
240             } else {
241                 button_create.setStyle('display', 'none');
242             }
244             // setup 'download this folder' button
245             // NOTE: popup window must be enabled to perform download process
246             button_download.on('click',function() {
247                 var scope = this;
248                 // perform downloaddir ajax request
249                 this.request({
250                     action: 'downloaddir',
251                     scope: scope,
252                     callback: function(id, obj, args) {
253                         if (obj) {
254                             scope.refresh(obj.filepath);
255                             var win = window.open(obj.fileurl, 'fm-download-folder');
256                             if (!win) {
257                                 alert(M.str.repository.popupblockeddownload);
258                             }
259                         } else {
260                             alert(M.str.repository.draftareanofiles);
261                         }
262                     }
263                 });
264             }, this);
265         },
266         empty_filelist: function(container) {
267             container.set('innerHTML', '<div class="mdl-align">'+M.str.repository.nofilesattached+'</div>'+this.upload_message());
268         },
269         upload_message: function() {
270             var div = '<div id="filemanager-uploadmessage'+this.client_id+'" style="display:none" class="dndupload-target">';
271             div += M.util.get_string('droptoupload', 'moodle');
272             div += '</div>';
273             return div;
274         },
275         render: function() {
276             var options = this.options;
277             var path = this.options.path;
278             var list = this.options.list;
279             var breadcrumb = Y.one('#fm-path-'+this.client_id);
280             // build breadcrumb
281             if (path) {
282                 // empty breadcrumb
283                 breadcrumb.set('innerHTML', '');
284                 var count = 0;
285                 for(var p in path) {
286                     var arrow = '';
287                     if (count==0) {
288                         arrow = Y.Node.create('<span>'+M.str.moodle.path + ': </span>');
289                     } else {
290                         arrow = Y.Node.create('<span> ▶ </span>');
291                     }
292                     count++;
294                     var pathid  = 'fm-path-node-'+this.client_id;
295                     pathid += ('-'+count);
297                     var crumb = Y.Node.create('<a href="###" id="'+pathid+'">'+path[p].name+'</a>');
298                     breadcrumb.appendChild(arrow);
299                     breadcrumb.appendChild(crumb);
301                     var args = {};
302                     args.requestpath = path[p].path;
303                     args.client_id = this.client_id;
304                     Y.one('#'+pathid).on('click', function(e, args) {
305                         var scope = this;
306                         var params = {};
307                         params['filepath'] = args.requestpath;
308                         this.currentpath = args.requestpath;
309                         this.request({
310                             action: 'list',
311                             scope: scope,
312                             params: params,
313                             callback: function(id, obj, args) {
314                                 scope.filecount = obj.filecount;
315                                 scope.check_buttons();
316                                 scope.options = obj;
317                                 scope.render(obj);
318                             }
319                         }, true);
320                     }, this, args);
321                 }
322             }
323             var template = Y.one('#fm-template');
324             var container = Y.one('#filemanager-' + this.client_id);
325             var listhtml = '';
327             // folder list items
328             var folder_ids = [];
329             var folder_data = {};
331             // normal file list items
332             var file_ids   = [];
333             var file_data  = {};
335             // archives list items
336             var zip_ids    = [];
337             var zip_data = {};
339             var html_ids = [];
340             var html_data = {};
342             file_data.itemid = folder_data.itemid = zip_data.itemid = options.itemid;
343             file_data.client_id = folder_data.client_id = zip_data.client_id = this.client_id;
345             var foldername_ids = [];
346             if (!list || list.length == 0) {
347                 // hide file browser and breadcrumb
348                 //container.setStyle('display', 'none');
349                 this.empty_filelist(container);
350                 if (!path || path.length <= 1) {
351                     breadcrumb.setStyle('display', 'none');
352                 }
353                 return;
354             } else {
355                 container.setStyle('display', 'block');
356                 breadcrumb.setStyle('display', 'block');
357             }
359             var count = 0;
360             for(var i in list) {
361                 count++;
362                 // the li html element
363                 var htmlid = 'fileitem-'+this.client_id+'-'+count;
364                 // link to file
365                 var fileid = 'filename-'+this.client_id+'-'+count;
366                 // file menu
367                 var action = 'action-'  +this.client_id+'-'+count;
369                 var html = template.get('innerHTML');
371                 html_ids.push('#'+htmlid);
372                 html_data[htmlid] = action;
374                 list[i].htmlid = htmlid;
375                 list[i].fileid = fileid;
376                 list[i].action = action;
378                 var url = "###";
380                 switch (list[i].type) {
381                     case 'folder':
382                         // click folder name
383                         foldername_ids.push('#'+fileid);
384                         // click folder menu
385                         folder_ids.push('#'+action);
386                         folder_data[action] = list[i];
387                         folder_data[fileid] = list[i];
388                         break;
389                     case 'file':
390                         file_ids.push('#'+action);
391                         // click file name
392                         file_ids.push('#'+fileid);
393                         file_data[action] = list[i];
394                         file_data[fileid] = list[i];
395                         if (list[i].url) {
396                             url = list[i].url;
397                         }
398                     break;
399                     case 'zip':
400                         zip_ids.push('#'+action);
401                         zip_ids.push('#'+fileid);
402                         zip_data[action] = list[i];
403                         zip_data[fileid] = list[i];
404                         if (list[i].url) {
405                             url = list[i].url;
406                         }
407                     break;
408                 }
409                 var fullname = list[i].fullname;
411                 if (list[i].sortorder == 1) {
412                     html = html.replace('___fullname___', '<strong><a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a></strong>');
413                 } else {
414                     html = html.replace('___fullname___', '<a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a>');
415                 }
416                 html = html.replace('___action___', '<span class="fm-menuicon" id="'+action+'"><img alt="▶" src="'+M.util.image_url('i/menu')+'" /></span>');
417                 html = '<li id="'+htmlid+'">'+html+'</li>';
418                 listhtml += html;
419             }
420             if (!Y.one('#draftfiles-'+this.client_id)) {
421                 var filelist = Y.Node.create('<ul id="draftfiles-'+this.client_id+'"></ul>');
422                 container.appendChild(filelist);
423             }
424             listhtml += this.upload_message();
425             Y.one('#draftfiles-'+this.client_id).set('innerHTML', listhtml);
427             // click normal file menu
428             Y.on('click', this.create_filemenu, file_ids, this, file_data);
429             Y.on('contextmenu', this.create_filemenu, file_ids, this, file_data);
430             // click folder menu
431             Y.on('click', this.create_foldermenu, folder_ids, this, folder_data);
432             Y.on('contextmenu', this.create_foldermenu, folder_ids, this, folder_data);
433             Y.on('contextmenu', this.create_foldermenu, foldername_ids, this, folder_data);
434             // click archievs menu
435             Y.on('click', this.create_zipmenu, zip_ids, this, zip_data);
436             Y.on('contextmenu', this.create_zipmenu, zip_ids, this, zip_data);
437             // click folder name
438             Y.on('click', this.enter_folder, foldername_ids, this, folder_data);
439         },
440         enter_folder: function(e, data) {
441             var node = e.currentTarget;
442             var file = data[node.get('id')];
443             this.refresh(file.filepath);
444         },
445         create_filemenu: function(e, data) {
446             e.preventDefault();
447             var options = this.options;
448             var node = e.currentTarget;
449             var file = data[node.get('id')];
450             var scope = this;
452             var menuitems = [
453                 {text: M.str.moodle.download, url:file.url}
454                 ];
455             function setmainfile(type, ev, obj) {
456                 var file = obj[node.get('id')];
457                 //Y.one(mainid).set('value', file.filepath+file.filename);
458                 var params = {};
459                 params['filepath']   = file.filepath;
460                 params['filename']   = file.filename;
461                 this.request({
462                     action: 'setmainfile',
463                     scope: scope,
464                     params: params,
465                     callback: function(id, obj, args) {
466                         scope.refresh(scope.currentpath);
467                     }
468                 });
469             }
470             if (this.enablemainfile && (file.sortorder != 1)) {
471                 var mainid = '#id_'+this.enablemainfile;
472                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
473                 menuitems.push(menu);
474             }
475             this.create_menu(e, 'filemenu', menuitems, file, data);
476         },
477         create_foldermenu: function(e, data) {
478             e.preventDefault();
479             var scope = this;
480             var node = e.currentTarget;
481             var fileinfo = data[node.get('id')];
482             // an extra menu item for folder to zip it
483             function archive_folder(type,ev,obj) {
484                 var params = {};
485                 params['filepath']   = fileinfo.filepath;
486                 params['filename']   = '.';
487                 this.request({
488                     action: 'zip',
489                     scope: scope,
490                     params: params,
491                     callback: function(id, obj, args) {
492                         scope.refresh(obj.filepath);
493                     }
494                 });
495             }
496             var menuitems = [
497                 {text: M.str.editor.zip, onclick: {fn: archive_folder, obj: data, scope: this}},
498                 ];
499             this.create_menu(e, 'foldermenu', menuitems, fileinfo, data);
500         },
501         create_zipmenu: function(e, data) {
502             e.preventDefault();
503             var scope = this;
504             var node = e.currentTarget;
505             var fileinfo = data[node.get('id')];
507             function unzip(type, ev, obj) {
508                 var params = {};
509                 params['filepath'] = fileinfo.filepath;
510                 params['filename'] = fileinfo.fullname;
511                 this.request({
512                     action: 'unzip',
513                     scope: scope,
514                     params: params,
515                     callback: function(id, obj, args) {
516                         scope.refresh(obj.filepath);
517                     }
518                 });
519             }
520             var menuitems = [
521                 {text: M.str.moodle.download, url:fileinfo.url},
522                 {text: M.str.moodle.unzip, onclick: {fn: unzip, obj: data, scope: this}}
523                 ];
524             function setmainfile(type, ev, obj) {
525                 var file = obj[node.get('id')];
526                 //Y.one(mainid).set('value', file.filepath+file.filename);
527                 var params = {};
528                 params['filepath']   = file.filepath;
529                 params['filename']   = file.filename;
530                 this.request({
531                     action: 'setmainfile',
532                     scope: scope,
533                     params: params,
534                     callback: function(id, obj, args) {
535                         scope.refresh(scope.currentpath);
536                     }
537                 });
538             }
539             if (this.enablemainfile && (fileinfo.sortorder != 1)) {
540                 var mainid = '#id_'+this.enablemainfile;
541                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
542                 menuitems.push(menu);
543             }
544             this.create_menu(e, 'zipmenu', menuitems, fileinfo, data);
545         },
546         create_menu: function(ev, menuid, menuitems, fileinfo, options) {
547             var position = [ev.pageX, ev.pageY];
548             var scope = this;
549             function remove(type, ev, obj) {
550                 var dialog_options = {};
551                 var params = {};
552                 dialog_options.message = M.str.repository.confirmdeletefile;
553                 dialog_options.scope = this;
554                 var filename = '';
555                 var filepath = '';
556                 if (fileinfo.type == 'folder') {
557                     params.filename = '.';
558                     params.filepath = fileinfo.filepath;
559                 } else {
560                     params.filename = fileinfo.fullname;
561                 }
562                 dialog_options.callbackargs = [params];
563                 dialog_options.callback = function(params) {
564                     this.request({
565                         action: 'delete',
566                         scope: this,
567                         params: params,
568                         callback: function(id, obj, args) {
569                             scope.filecount--;
570                             scope.refresh(obj.filepath);
571                             M.util.set_form_changed();
572                             if (scope.filecount < scope.maxfiles && scope.maxfiles!=-1) {
573                                 var button_addfile  = Y.one("#btnadd-"+scope.client_id);
574                                 button_addfile.setStyle('display', 'inline');
575                                 button_addfile.on('click', function(e) {
576                                     var options = scope.filepicker_options;
577                                     options.formcallback = scope.filepicker_callback;
578                                     // XXX: magic here, to let filepicker use filemanager scope
579                                     options.magicscope = scope;
580                                     options.savepath = scope.currentpath;
581                                     M.core_filepicker.show(Y, options);
582                                 }, this);
583                             }
584                         }
585                     });
586                 };
587                 M.util.show_confirm_dialog(ev, dialog_options);
588             }
589             function rename (type, ev, obj) {
590                 var scope = this;
591                 var perform = function(e) {
592                     var newfilename = Y.one('#fm-rename-input').get('value');
593                     if (!newfilename) {
594                         return;
595                     }
597                     var action = '';
598                     var params = {};
599                     if (fileinfo.type == 'folder') {
600                         params['filepath']   = fileinfo.filepath;
601                         params['filename']   = '.';
602                         params['newdirname'] = newfilename;
603                         action = 'renamedir';
604                     } else {
605                         params['filepath']   = fileinfo.filepath;
606                         params['filename']   = fileinfo.fullname;
607                         params['newfilename'] = newfilename;
608                         action = 'rename';
609                     }
610                     scope.request({
611                         action: action,
612                         scope: scope,
613                         params: params,
614                         callback: function(id, obj, args) {
615                             if (obj == false) {
616                                 alert(M.str.repository.fileexists);
617                             } else {
618                                 scope.refresh(obj.filepath);
619                                 M.util.set_form_changed();
620                             }
621                             Y.one('#fm-rename-input').set('value', '');
622                             scope.rename_dialog.hide();
623                         }
624                     });
625                 };
627                 var dialog = Y.one('#fm-rename-dlg');
628                 if (!dialog) {
629                     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>');
630                     Y.one(document.body).appendChild(dialog);
631                     this.rename_dialog = new YAHOO.widget.Dialog("fm-rename-dlg", {
632                          width: "300px",
633                          fixedcenter: true,
634                          visible: true,
635                          constraintoviewport : true
636                          });
638                 }
639                 var buttons = [ { text:M.str.moodle.rename, handler:perform, isDefault:true},
640                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
642                 this.rename_dialog.cfg.queueProperty('buttons', buttons);
643                 this.rename_dialog.render();
644                 this.rename_dialog.show();
645                 //var k1 = new YAHOO.util.KeyListener(scope, {keys:13}, {fn:function(){perform();}, correctScope: true});
646                 //k1.enable();
647                 Y.one('#fm-rename-input').set('value', fileinfo.fullname);
648             }
649             function move(type, ev, obj) {
650                 var scope = this;
651                 var itemid = this.options.itemid;
652                 // setup move file dialog
653                 var dialog = null;
654                 if (!Y.one('#fm-move-dlg')) {
655                     dialog = Y.Node.create('<div id="fm-move-dlg"></div>');
656                     Y.one(document.body).appendChild(dialog);
657                 } else {
658                     dialog = Y.one('#fm-move-dlg');
659                 }
661                 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>');
663                 this.movefile_dialog = new YAHOO.widget.Dialog("fm-move-dlg", {
664                      width : "600px",
665                      fixedcenter : true,
666                      visible : false,
667                      constraintoviewport : true
668                      });
670                 var treeview = new YAHOO.widget.TreeView("fm-tree");
672                 var dialog = this.movefile_dialog;
673                 function _move(e) {
674                     if (!treeview.targetpath) {
675                         return;
676                     }
677                     var params = {};
678                     if (fileinfo.type == 'folder') {
679                         action = 'movedir';
680                     } else {
681                         action = 'movefile';
682                     }
683                     params['filepath'] = fileinfo.filepath;
684                     params['filename'] = fileinfo.fullname;
685                     params['newfilepath'] = treeview.targetpath;
686                     scope.request({
687                         action: action,
688                         scope: scope,
689                         params: params,
690                         callback: function(id, obj, args) {
691                             var p = '/';
692                             if (obj) {
693                                 p = obj.filepath;
694                             }
695                             dialog.cancel();
696                             scope.refresh(p);
697                             M.util.set_form_changed();
698                         }
699                     });
700                 }
702                 var buttons = [ { text:M.str.moodle.move, handler:_move, isDefault:true },
703                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
705                 this.movefile_dialog.cfg.queueProperty("buttons", buttons);
706                 this.movefile_dialog.render();
708                 treeview.subscribe("dblClickEvent", function(e) {
709                     // update destidatoin folder
710                     this.targetpath = e.node.data.path;
711                     var title = Y.one('#fm-move-div');
712                     title.set('innerHTML', '<strong>"' + this.targetpath + '"</strong> has been selected.');
713                 });
715                 function loadDataForNode(node, onCompleteCallback) {
716                     var params = {};
717                     params['filepath'] = node.data.path;
718                     var obj = {
719                         action: 'dir',
720                         scope: scope,
721                         params: params,
722                         callback: function(id, obj, args) {
723                             data = obj.children;
724                             if (data.length == 0) {
725                                 // so it is empty
726                             } else {
727                                 for (var i in data) {
728                                     var textnode = {label: data[i].fullname, path: data[i].filepath, itemid: this.itemid};
729                                     var tmpNode = new YAHOO.widget.TextNode(textnode, node, false);
730                                 }
731                             }
732                             this.oncomplete();
733                         }
734                     };
735                     obj.oncomplete = onCompleteCallback;
736                     scope.request(obj);
737                 }
739                 this.movefile_dialog.subscribe('show', function(){
740                     var rootNode = treeview.getRoot();
741                     treeview.setDynamicLoad(loadDataForNode);
742                     treeview.removeChildren(rootNode);
743                     var textnode = {label: M.str.moodle.files, path: '/'};
744                     var tmpNode = new YAHOO.widget.TextNode(textnode, rootNode, true);
745                     treeview.draw();
746                 }, this, true);
748                 this.movefile_dialog.show();
749             }
750             var shared_items = [
751                 {text: M.str.moodle.rename+'...', onclick: {fn: rename, obj: options, scope: this}},
752                 {text: M.str.moodle.move+'...', onclick: {fn: move, obj: options, scope: this}}
753             ];
754             // delete is reserve word in Javascript
755             shared_items.push({text: M.str.moodle['delete']+'...', onclick: {fn: remove, obj: options, scope: this}});
756             var menu = new YAHOO.widget.Menu(menuid, {xy:position, clicktohide:true});
757             menu.clearContent();
758             menu.addItems(menuitems);
759             menu.addItems(shared_items);
760             menu.render(document.body);
761             menu.subscribe('hide', function(){
762                 this.fireEvent('destroy');
763             });
764             menu.show();
765         }
766     });
768     // finally init everything needed
769     // kill nonjs filemanager
770     var item = document.getElementById('nonjs-filemanager-'+options.client_id);
771     if (item && !options.usenonjs) {
772         item.parentNode.removeChild(item);
773     }
774     // hide loading picture
775     item = document.getElementById('filemanager-loading-'+options.client_id);
776     if (item) {
777         item.parentNode.removeChild(item);
778     }
779     // display filemanager interface
780     item = document.getElementById('filemanager-wrapper-'+options.client_id);
781     if (item) {
782         item.style.display = '';
783     }
785     var manager = new FileManagerHelper(options);
786     var dndoptions = {
787         filemanager: manager,
788         acceptedtypes: options.accepted_types,
789         clientid: options.client_id,
790         maxfiles: options.maxfiles,
791         maxbytes: options.maxbytes,
792         itemid: options.itemid,
793         repositories: manager.filepicker_options.repositories,
794         containerprefix: '#filemanager-',
795     };
796     M.form_dndupload.init(Y, dndoptions);
797 };