MDL-31656 Open files in a new window when downloading with the filemanager
[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, onclick:{fn:open_file_in_new_window, obj:file, scope:this}}
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             function open_file_in_new_window(type, ev, obj) {
471                 // We open in a new window rather than changing the current windows URL as we don't
472                 // want to navigate away from the page
473                 window.open(obj.url, 'fm-download-file');
474             }
475             if (this.enablemainfile && (file.sortorder != 1)) {
476                 var mainid = '#id_'+this.enablemainfile;
477                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
478                 menuitems.push(menu);
479             }
480             this.create_menu(e, 'filemenu', menuitems, file, data);
481         },
482         create_foldermenu: function(e, data) {
483             e.preventDefault();
484             var scope = this;
485             var node = e.currentTarget;
486             var fileinfo = data[node.get('id')];
487             // an extra menu item for folder to zip it
488             function archive_folder(type,ev,obj) {
489                 var params = {};
490                 params['filepath']   = fileinfo.filepath;
491                 params['filename']   = '.';
492                 this.request({
493                     action: 'zip',
494                     scope: scope,
495                     params: params,
496                     callback: function(id, obj, args) {
497                         scope.refresh(obj.filepath);
498                     }
499                 });
500             }
501             var menuitems = [
502                 {text: M.str.editor.zip, onclick: {fn: archive_folder, obj: data, scope: this}},
503                 ];
504             this.create_menu(e, 'foldermenu', menuitems, fileinfo, data);
505         },
506         create_zipmenu: function(e, data) {
507             e.preventDefault();
508             var scope = this;
509             var node = e.currentTarget;
510             var fileinfo = data[node.get('id')];
512             function unzip(type, ev, obj) {
513                 var params = {};
514                 params['filepath'] = fileinfo.filepath;
515                 params['filename'] = fileinfo.fullname;
516                 this.request({
517                     action: 'unzip',
518                     scope: scope,
519                     params: params,
520                     callback: function(id, obj, args) {
521                         scope.refresh(obj.filepath);
522                     }
523                 });
524             }
525             var menuitems = [
526                 {text: M.str.moodle.download, url:fileinfo.url},
527                 {text: M.str.moodle.unzip, onclick: {fn: unzip, obj: data, scope: this}}
528                 ];
529             function setmainfile(type, ev, obj) {
530                 var file = obj[node.get('id')];
531                 //Y.one(mainid).set('value', file.filepath+file.filename);
532                 var params = {};
533                 params['filepath']   = file.filepath;
534                 params['filename']   = file.filename;
535                 this.request({
536                     action: 'setmainfile',
537                     scope: scope,
538                     params: params,
539                     callback: function(id, obj, args) {
540                         scope.refresh(scope.currentpath);
541                     }
542                 });
543             }
544             if (this.enablemainfile && (fileinfo.sortorder != 1)) {
545                 var mainid = '#id_'+this.enablemainfile;
546                 var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
547                 menuitems.push(menu);
548             }
549             this.create_menu(e, 'zipmenu', menuitems, fileinfo, data);
550         },
551         create_menu: function(ev, menuid, menuitems, fileinfo, options) {
552             var position = [ev.pageX, ev.pageY];
553             var scope = this;
554             function remove(type, ev, obj) {
555                 var dialog_options = {};
556                 var params = {};
557                 dialog_options.message = M.str.repository.confirmdeletefile;
558                 dialog_options.scope = this;
559                 var filename = '';
560                 var filepath = '';
561                 if (fileinfo.type == 'folder') {
562                     params.filename = '.';
563                     params.filepath = fileinfo.filepath;
564                 } else {
565                     params.filename = fileinfo.fullname;
566                 }
567                 dialog_options.callbackargs = [params];
568                 dialog_options.callback = function(params) {
569                     this.request({
570                         action: 'delete',
571                         scope: this,
572                         params: params,
573                         callback: function(id, obj, args) {
574                             scope.filecount--;
575                             scope.refresh(obj.filepath);
576                             M.util.set_form_changed();
577                             if (scope.filecount < scope.maxfiles && scope.maxfiles!=-1) {
578                                 var button_addfile  = Y.one("#btnadd-"+scope.client_id);
579                                 button_addfile.setStyle('display', 'inline');
580                                 button_addfile.on('click', function(e) {
581                                     var options = scope.filepicker_options;
582                                     options.formcallback = scope.filepicker_callback;
583                                     // XXX: magic here, to let filepicker use filemanager scope
584                                     options.magicscope = scope;
585                                     options.savepath = scope.currentpath;
586                                     M.core_filepicker.show(Y, options);
587                                 }, this);
588                             }
589                         }
590                     });
591                 };
592                 M.util.show_confirm_dialog(ev, dialog_options);
593             }
594             function rename (type, ev, obj) {
595                 var scope = this;
596                 var perform = function(e) {
597                     var newfilename = Y.one('#fm-rename-input').get('value');
598                     if (!newfilename) {
599                         return;
600                     }
602                     var action = '';
603                     var params = {};
604                     if (fileinfo.type == 'folder') {
605                         params['filepath']   = fileinfo.filepath;
606                         params['filename']   = '.';
607                         params['newdirname'] = newfilename;
608                         action = 'renamedir';
609                     } else {
610                         params['filepath']   = fileinfo.filepath;
611                         params['filename']   = fileinfo.fullname;
612                         params['newfilename'] = newfilename;
613                         action = 'rename';
614                     }
615                     scope.request({
616                         action: action,
617                         scope: scope,
618                         params: params,
619                         callback: function(id, obj, args) {
620                             if (obj == false) {
621                                 alert(M.str.repository.fileexists);
622                             } else {
623                                 scope.refresh(obj.filepath);
624                                 M.util.set_form_changed();
625                             }
626                             Y.one('#fm-rename-input').set('value', '');
627                             scope.rename_dialog.hide();
628                         }
629                     });
630                 };
632                 var dialog = Y.one('#fm-rename-dlg');
633                 if (!dialog) {
634                     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>');
635                     Y.one(document.body).appendChild(dialog);
636                     this.rename_dialog = new YAHOO.widget.Dialog("fm-rename-dlg", {
637                          width: "300px",
638                          fixedcenter: true,
639                          visible: true,
640                          constraintoviewport : true
641                          });
643                 }
644                 var buttons = [ { text:M.str.moodle.rename, handler:perform, isDefault:true},
645                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
647                 this.rename_dialog.cfg.queueProperty('buttons', buttons);
648                 this.rename_dialog.render();
649                 this.rename_dialog.show();
650                 //var k1 = new YAHOO.util.KeyListener(scope, {keys:13}, {fn:function(){perform();}, correctScope: true});
651                 //k1.enable();
652                 Y.one('#fm-rename-input').set('value', fileinfo.fullname);
653             }
654             function move(type, ev, obj) {
655                 var scope = this;
656                 var itemid = this.options.itemid;
657                 // setup move file dialog
658                 var dialog = null;
659                 if (!Y.one('#fm-move-dlg')) {
660                     dialog = Y.Node.create('<div id="fm-move-dlg"></div>');
661                     Y.one(document.body).appendChild(dialog);
662                 } else {
663                     dialog = Y.one('#fm-move-dlg');
664                 }
666                 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>');
668                 this.movefile_dialog = new YAHOO.widget.Dialog("fm-move-dlg", {
669                      width : "600px",
670                      fixedcenter : true,
671                      visible : false,
672                      constraintoviewport : true
673                      });
675                 var treeview = new YAHOO.widget.TreeView("fm-tree");
677                 var dialog = this.movefile_dialog;
678                 function _move(e) {
679                     if (!treeview.targetpath) {
680                         return;
681                     }
682                     var params = {};
683                     if (fileinfo.type == 'folder') {
684                         action = 'movedir';
685                     } else {
686                         action = 'movefile';
687                     }
688                     params['filepath'] = fileinfo.filepath;
689                     params['filename'] = fileinfo.fullname;
690                     params['newfilepath'] = treeview.targetpath;
691                     scope.request({
692                         action: action,
693                         scope: scope,
694                         params: params,
695                         callback: function(id, obj, args) {
696                             var p = '/';
697                             if (obj) {
698                                 p = obj.filepath;
699                             }
700                             dialog.cancel();
701                             scope.refresh(p);
702                             M.util.set_form_changed();
703                         }
704                     });
705                 }
707                 var buttons = [ { text:M.str.moodle.move, handler:_move, isDefault:true },
708                                   { text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
710                 this.movefile_dialog.cfg.queueProperty("buttons", buttons);
711                 this.movefile_dialog.render();
713                 treeview.subscribe("dblClickEvent", function(e) {
714                     // update destidatoin folder
715                     this.targetpath = e.node.data.path;
716                     var title = Y.one('#fm-move-div');
717                     title.set('innerHTML', '<strong>"' + this.targetpath + '"</strong> has been selected.');
718                 });
720                 function loadDataForNode(node, onCompleteCallback) {
721                     var params = {};
722                     params['filepath'] = node.data.path;
723                     var obj = {
724                         action: 'dir',
725                         scope: scope,
726                         params: params,
727                         callback: function(id, obj, args) {
728                             data = obj.children;
729                             if (data.length == 0) {
730                                 // so it is empty
731                             } else {
732                                 for (var i in data) {
733                                     var textnode = {label: data[i].fullname, path: data[i].filepath, itemid: this.itemid};
734                                     var tmpNode = new YAHOO.widget.TextNode(textnode, node, false);
735                                 }
736                             }
737                             this.oncomplete();
738                         }
739                     };
740                     obj.oncomplete = onCompleteCallback;
741                     scope.request(obj);
742                 }
744                 this.movefile_dialog.subscribe('show', function(){
745                     var rootNode = treeview.getRoot();
746                     treeview.setDynamicLoad(loadDataForNode);
747                     treeview.removeChildren(rootNode);
748                     var textnode = {label: M.str.moodle.files, path: '/'};
749                     var tmpNode = new YAHOO.widget.TextNode(textnode, rootNode, true);
750                     treeview.draw();
751                 }, this, true);
753                 this.movefile_dialog.show();
754             }
755             var shared_items = [
756                 {text: M.str.moodle.rename+'...', onclick: {fn: rename, obj: options, scope: this}},
757                 {text: M.str.moodle.move+'...', onclick: {fn: move, obj: options, scope: this}}
758             ];
759             // delete is reserve word in Javascript
760             shared_items.push({text: M.str.moodle['delete']+'...', onclick: {fn: remove, obj: options, scope: this}});
761             var menu = new YAHOO.widget.Menu(menuid, {xy:position, clicktohide:true});
762             menu.clearContent();
763             menu.addItems(menuitems);
764             menu.addItems(shared_items);
765             menu.render(document.body);
766             menu.subscribe('hide', function(){
767                 this.fireEvent('destroy');
768             });
769             menu.show();
770         }
771     });
773     // finally init everything needed
774     // kill nonjs filemanager
775     var item = document.getElementById('nonjs-filemanager-'+options.client_id);
776     if (item && !options.usenonjs) {
777         item.parentNode.removeChild(item);
778     }
779     // hide loading picture
780     item = document.getElementById('filemanager-loading-'+options.client_id);
781     if (item) {
782         item.parentNode.removeChild(item);
783     }
784     // display filemanager interface
785     item = document.getElementById('filemanager-wrapper-'+options.client_id);
786     if (item) {
787         item.style.display = '';
788     }
790     var manager = new FileManagerHelper(options);
791     var dndoptions = {
792         filemanager: manager,
793         acceptedtypes: options.accepted_types,
794         clientid: options.client_id,
795         maxfiles: options.maxfiles,
796         maxbytes: options.maxbytes,
797         itemid: options.itemid,
798         repositories: manager.filepicker_options.repositories,
799         containerprefix: '#filemanager-',
800     };
801     M.form_dndupload.init(Y, dndoptions);
802 };