Automatically generated installer lang files
[moodle.git] / lib / form / filemanager.js
blobee94df516c6649f9cd316461145afb9ebbddc16e
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  * this.areamaxbytes, the maximum size of the area
30  * this.filemanager, contains reference to filemanager Node
31  * this.selectnode, contains referenct to select-file Node
32  * this.selectui, M.core.dialogue to select the file
33  * this.viewmode, contains current view mode - icons, tree or details
34  *
35  * FileManager options:
36  * =====
37  * this.options.currentpath
38  * this.options.itemid
39  */
41 /* eslint camelcase: off */
43 M.form_filemanager = {
44     templates: {},
45     formChangeChecker: null,
48 require(['core_form/changechecker'], function(FormChangeChecker) {
49     // This is a nasty, hacky, way of doing it but it's the smallest evil.
50     M.form_filemanager.formChangeChecker = FormChangeChecker;
51 });
53 M.form_filemanager.set_templates = function(Y, templates) {
54     M.form_filemanager.templates = templates;
57 /**
58  * This fucntion is called for each file picker on page.
59  */
60 M.form_filemanager.init = function(Y, options) {
61     var FileManagerHelper = function(options) {
62         FileManagerHelper.superclass.constructor.apply(this, arguments);
63     };
64     FileManagerHelper.NAME = "FileManager";
65     FileManagerHelper.ATTRS = {
66         options: {},
67         lang: {}
68     };
70     Y.extend(FileManagerHelper, Y.Base, {
71         api: M.cfg.wwwroot+'/repository/draftfiles_ajax.php',
72         menus: {},
73         initializer: function(options) {
74             this.options = options;
75             if (options.mainfile) {
76                 this.enablemainfile = options.mainfile;
77             }
78             this.client_id = options.client_id;
79             this.currentpath = '/';
80             this.maxfiles = options.maxfiles;
81             this.maxbytes = options.maxbytes;
82             this.areamaxbytes = options.areamaxbytes;
83             this.userprefs = options.userprefs;
84             this.emptycallback = null; // Used by drag and drop upload
86             this.filepicker_options = options.filepicker?options.filepicker:{};
87             this.filepicker_options.client_id = this.client_id;
88             this.filepicker_options.context = options.context;
89             this.filepicker_options.maxfiles = this.maxfiles;
90             this.filepicker_options.maxbytes = this.maxbytes;
91             this.filepicker_options.areamaxbytes = this.areamaxbytes;
92             this.filepicker_options.env = 'filemanager';
93             this.filepicker_options.itemid = options.itemid;
95             if (options.filecount) {
96                 this.filecount = options.filecount;
97             } else {
98                 this.filecount = 0;
99             }
100             // prepare filemanager for drag-and-drop upload
101             this.filemanager = Y.one('#filemanager-'+options.client_id);
102             if (this.filemanager.hasClass('filemanager-container') || !this.filemanager.one('.filemanager-container')) {
103                 this.dndcontainer = this.filemanager;
104             } else  {
105                 this.dndcontainer = this.filemanager.one('.filemanager-container');
106                 if (!this.dndcontainer.get('id')) {
107                     this.dndcontainer.generateID();
108                 }
109             }
110             // save template for one path element and location of path bar
111             if (this.filemanager.one('.fp-path-folder')) {
112                 this.pathnode = this.filemanager.one('.fp-path-folder');
113                 this.pathbar = this.pathnode.get('parentNode');
114                 this.pathbar.removeChild(this.pathnode);
115             }
116             // initialize 'select file' panel
117             this.selectnode = Y.Node.create(M.form_filemanager.templates.fileselectlayout);
118             this.selectnode.setAttribute('aria-live', 'assertive');
119             this.selectnode.setAttribute('role', 'dialog');
120             this.selectnode.generateID();
122             var labelid = 'fm-dialog-label_'+ this.selectnode.get('id');
123             this.selectui = new M.core.dialogue({
124                 draggable    : true,
125                 headerContent: '<h3 id="' + labelid +'">' + M.util.get_string('edit', 'moodle') + '</h3>',
126                 bodyContent  : this.selectnode,
127                 centered     : true,
128                 width        : '480px',
129                 modal        : true,
130                 visible      : false
131             });
132             Y.one('#'+this.selectnode.get('id')).setAttribute('aria-labelledby', labelid);
133             this.selectui.hide();
134             this.setup_select_file();
135             // setup buttons onclick events
136             this.setup_buttons();
137             // set event handler for lazy loading of thumbnails
138             this.filemanager.one('.fp-content').on(['scroll','resize'], this.content_scrolled, this);
139             // display files
140             this.viewmode = this.get_preference("recentviewmode");
141             if (this.viewmode != 2 && this.viewmode != 3) {
142                 this.viewmode = 1;
143             }
144             var viewmodeselectors = {'1': '.fp-vb-icons', '2': '.fp-vb-tree', '3': '.fp-vb-details'};
145             this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').removeClass('checked');
146             this.filemanager.all(viewmodeselectors[this.viewmode]).addClass('checked');
147             this.refresh(this.currentpath); // MDL-31113 get latest list from server
148         },
150         wait: function() {
151            this.filemanager.addClass('fm-updating');
152         },
153         request: function(args, redraw) {
154             var api = this.api + '?action='+args.action;
155             var params = {};
156             var scope = this;
157             if (args['scope']) {
158                 scope = args['scope'];
159             }
160             params['sesskey'] = M.cfg.sesskey;
161             params['client_id'] = this.client_id;
162             params['filepath'] = this.currentpath;
163             params['itemid'] = this.options.itemid?this.options.itemid:0;
164             if (args['params']) {
165                 for (i in args['params']) {
166                     params[i] = args['params'][i];
167                 }
168             }
169             var cfg = {
170                 method: 'POST',
171                 on: {
172                     complete: function(id,o,p) {
173                         if (!o) {
174                             alert('IO FATAL');
175                             return;
176                         }
177                         var data = null;
178                         try {
179                             data = Y.JSON.parse(o.responseText);
180                         } catch(e) {
181                             scope.print_msg(M.util.get_string('invalidjson', 'repository'), 'error');
182                             Y.error(M.util.get_string('invalidjson', 'repository')+":\n"+o.responseText);
183                             return;
184                         }
185                         if (data && data.tree && scope.set_current_tree) {
186                             scope.set_current_tree(data.tree);
187                         }
188                         args.callback(id,data,p);
189                     }
190                 },
191                 arguments: {
192                     scope: scope
193                 },
194                 headers: {
195                     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
196                 },
197                 data: build_querystring(params)
198             };
199             if (args.form) {
200                 cfg.form = args.form;
201             }
202             Y.io(api, cfg);
203             if (redraw) {
204                 this.wait();
205             }
206         },
207         filepicker_callback: function(obj) {
208             this.filecount++;
209             this.check_buttons();
210             this.refresh(this.currentpath);
211             M.form_filemanager.formChangeChecker.markFormChangedFromNode(this.filemanager.getDOMNode());
213             require(['core_form/events'], function(FormEvent) {
214                 FormEvent.notifyUploadChanged(this.filemanager.get('id'));
215             }.bind(this));
216         },
217         check_buttons: function() {
218             if (this.filecount>0) {
219                 this.filemanager.removeClass('fm-nofiles');
220             } else {
221                 this.filemanager.addClass('fm-nofiles');
222             }
223             if (this.filecount >= this.maxfiles && this.maxfiles!=-1) {
224                 this.filemanager.addClass('fm-maxfiles');
225             }
226             else {
227                 this.filemanager.removeClass('fm-maxfiles');
228             }
229         },
230         refresh: function(filepath, action) {
231             var scope = this;
232             this.currentpath = filepath;
233             if (!filepath) {
234                 filepath = this.currentpath;
235             } else {
236                 this.currentpath = filepath;
237             }
238             this.request({
239                 action: 'list',
240                 scope: scope,
241                 params: {'filepath':filepath},
242                 callback: function(id, obj, args) {
243                     scope.filecount = obj.filecount;
244                     scope.options = obj;
245                     scope.lazyloading = {};
246                     scope.check_buttons();
247                     scope.render(obj, action);
248                 }
249             }, true);
250         },
251         /** displays message in a popup */
252         print_msg: function(msg, type, options) {
253             var header = M.util.get_string('error', 'moodle');
254             if (type != 'error') {
255                 type = 'info'; // one of only two types excepted
256                 header = M.util.get_string('info', 'moodle');
257             }
258             if (!this.msg_dlg) {
259                 this.msg_dlg_node = Y.Node.create(M.form_filemanager.templates.message);
260                 var nodeid = this.msg_dlg_node.generateID();
261                 var previousActiveElement = null;
262                 if (typeof options.previousActiveElement != 'undefined') {
263                     previousActiveElement = options.previousActiveElement;
264                 }
265                 this.msg_dlg = new M.core.dialogue({
266                     draggable    : true,
267                     bodyContent  : this.msg_dlg_node,
268                     centered     : true,
269                     modal        : true,
270                     visible      : false,
271                     focusAfterHide: previousActiveElement,
272                 });
273                 this.msg_dlg_node.one('.fp-msg-butok').on('click', function(e) {
274                     e.preventDefault();
275                     this.msg_dlg.hide();
276                 }, this);
277             }
279             this.msg_dlg.set('headerContent', header);
280             this.msg_dlg_node.removeClass('fp-msg-info').removeClass('fp-msg-error').addClass('fp-msg-'+type)
281             this.msg_dlg_node.one('.fp-msg-text').setContent(Y.Escape.html(msg));
282             this.msg_dlg.show();
283         },
284         is_disabled: function() {
285             return this.filemanager.ancestor('.fitem.disabled') != null;
286         },
287         getSelectedFiles: function() {
288             var markedFiles = this.filemanager.all('[data-togglegroup=file-selections]:checked');
289             var filenames = [];
290             markedFiles.each(function(item) {
291                 var fileinfo = this.options.list.find(function(element) {
292                     return item.getData().fullname == element.fullname;
293                 });
294                 if (fileinfo && fileinfo != undefined) {
295                     filenames.push({
296                         filepath: fileinfo.filepath,
297                         filename: fileinfo.filename
298                     });
299                 }
300             }, this);
302             return filenames;
303         },
304         setup_buttons: function() {
305             var button_download = this.filemanager.one('.fp-btn-download');
306             var button_create   = this.filemanager.one('.fp-btn-mkdir');
307             var button_addfile  = this.filemanager.one('.fp-btn-add');
308             var buttonDeleteFile = this.filemanager.one('.fp-btn-delete');
310             // setup 'add file' button
311             button_addfile.on('click', this.show_filepicker, this);
313             var dndarrow = this.filemanager.one('.dndupload-arrow');
314             if (dndarrow) {
315                 dndarrow.on('click', this.show_filepicker, this);
316             }
318             // setup 'make a folder' button
319             if (this.options.subdirs) {
320                 button_create.on('click',function(e) {
321                     e.preventDefault();
322                     if (this.is_disabled()) {
323                         return;
324                     }
325                     var scope = this;
326                     // a function used to perform an ajax request
327                     var perform_action = function(e) {
328                         e.preventDefault();
329                         var foldername = Y.one('#fm-newname-'+scope.client_id).get('value');
330                         if (!foldername) {
331                             scope.mkdir_dialog.hide();
332                             return;
333                         }
334                         scope.request({
335                             action:'mkdir',
336                             params: {filepath:scope.currentpath, newdirname:foldername},
337                             callback: function(id, obj, args) {
338                                 var filepath = obj.filepath;
339                                 scope.mkdir_dialog.hide();
340                                 scope.refresh(filepath);
341                                 Y.one('#fm-newname-'+scope.client_id).set('value', '');
342                                 M.form_filemanager.formChangeChecker.markFormChangedFromNode(scope.filemanager.getDOMNode());
343                             }
344                         });
345                     };
346                     var validate_folder_name = function() {
347                         var valid = false;
348                         var foldername = Y.one('#fm-newname-'+scope.client_id).get('value');
349                         if (foldername.length > 0) {
350                             valid = true;
351                         }
352                         var btn = Y.one('#fm-mkdir-butcreate-'+scope.client_id);
353                         if (btn) {
354                             btn.set('disabled', !valid);
355                         }
356                         return valid;
357                     };
358                     if (!this.mkdir_dialog) {
359                         var node = Y.Node.create(M.form_filemanager.templates.mkdir);
360                         this.mkdir_dialog = new M.core.dialogue({
361                             draggable    : true,
362                             bodyContent  : node,
363                             centered     : true,
364                             modal        : true,
365                             visible      : false,
366                             focusAfterHide: e.target.ancestor('a', true),
367                         });
368                         node.one('.fp-dlg-butcreate').set('id', 'fm-mkdir-butcreate-'+this.client_id).on('click',
369                                 perform_action, this);
370                         node.one('input').set('id', 'fm-newname-'+this.client_id).on('keydown', function(e) {
371                             var valid = Y.bind(validate_folder_name, this)();
372                             if (valid && e.keyCode === 13) {
373                                 Y.bind(perform_action, this)(e);
374                             }
375                         }, this);
376                         node.one('#fm-newname-'+this.client_id).on(['keyup', 'change'], function(e) {
377                             Y.bind(validate_folder_name, this)();
378                         }, this);
380                         node.one('label').set('for', 'fm-newname-' + this.client_id);
381                         node.all('.fp-dlg-butcancel').on('click', function(e){e.preventDefault();this.mkdir_dialog.hide();}, this);
382                         node.all('.fp-dlg-curpath').set('id', 'fm-curpath-'+this.client_id);
383                     }
384                     this.mkdir_dialog.show();
386                     // Default folder name:
387                     var foldername = M.util.get_string('newfolder', 'repository');
388                     while (this.has_folder(foldername)) {
389                         foldername = increment_filename(foldername, true);
390                     }
391                     Y.one('#fm-newname-'+scope.client_id).set('value', foldername);
392                     Y.bind(validate_folder_name, this)();
393                     Y.one('#fm-newname-'+scope.client_id).focus().select();
394                     Y.all('#fm-curpath-'+scope.client_id).setContent(this.currentpath);
395                 }, this);
396             } else {
397                 this.filemanager.addClass('fm-nomkdir');
398             }
400             // setup 'download this folder' button
401             button_download.on('click',function(e) {
402                 e.preventDefault();
403                 if (this.is_disabled()) {
404                     return;
405                 }
406                 var scope = this;
408                 var image_downloading = this.filemanager.one('.fp-img-downloading');
409                 if (image_downloading.getStyle('display') == 'inline') {
410                     return;
411                 }
412                 image_downloading.setStyle('display', 'inline');
413                 var filenames = this.getSelectedFiles();
415                 // perform downloaddir ajax request
416                 this.request({
417                     action: 'downloadselected',
418                     scope: scope,
419                     params: {selected: Y.JSON.stringify(filenames)},
420                     callback: function(id, obj, args) {
421                         var image_downloading = scope.filemanager.one('.fp-img-downloading');
422                         image_downloading.setStyle('display', 'none');
424                         if (obj) {
425                             scope.refresh(obj.filepath);
426                             node = Y.Node.create('<iframe></iframe>').setStyles({
427                                 visibility : 'hidden',
428                                 width : '1px',
429                                 height : '1px'
430                             });
431                             node.set('src', obj.fileurl);
432                             Y.one('body').appendChild(node);
433                         } else {
434                             scope.print_msg(M.util.get_string('draftareanofiles', 'repository'), 'error');
435                         }
436                     }
437                 });
438             }, this);
440             buttonDeleteFile.on('click', function(e) {
441                 e.preventDefault();
442                 var dialogOptions = {};
443                 var filenames = this.getSelectedFiles();
444                 var previousActiveElement = e.target.ancestor('a', true);
446                 if (!filenames.length) {
447                     var options = {};
448                     options.previousActiveElement = previousActiveElement;
449                     this.print_msg(M.util.get_string('nofilesselected', 'repository'), 'error', options);
450                     return;
451                 }
453                 dialogOptions.scope = this;
454                 var params = {
455                     selected: Y.JSON.stringify(filenames)
456                 };
457                 dialogOptions.header = M.util.get_string('confirm', 'moodle');
458                 dialogOptions.message = M.util.get_string('confirmdeleteselectedfile', 'repository', filenames.length);
459                 dialogOptions.previousActiveElement = previousActiveElement;
460                 dialogOptions.callbackargs = [params];
461                 dialogOptions.callback = function(params) {
462                     this.request({
463                         action: 'deleteselected',
464                         scope: this,
465                         params: params,
466                         callback: function(id, obj, args) {
467                             // Do something here
468                             args.scope.filecount -= params.length;
469                             if (obj && obj.length) {
470                                 args.scope.refresh(obj[0], {action: 'delete'});
471                             }
472                             M.form_filemanager.formChangeChecker.markFormChangedFromNode(this.scope.filemanager.getDOMNode());
474                             require(['core_form/events'], function(FormEvent) {
475                                 FormEvent.notifyUploadChanged(this.scope.filemanager.get('id'));
476                             }.bind(this));
477                         }
478                     });
479                 };
480                 this.show_confirm_dialog(dialogOptions);
481             }, this);
483             this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').
484                 on('click', function(e) {
485                     e.preventDefault();
486                     var viewbar = this.filemanager.one('.fp-viewbar')
487                     if (!this.is_disabled() && (!viewbar || !viewbar.hasClass('disabled'))) {
488                         this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').removeClass('checked')
489                         if (e.currentTarget.hasClass('fp-vb-tree')) {
490                             this.viewmode = 2;
491                         } else if (e.currentTarget.hasClass('fp-vb-details')) {
492                             this.viewmode = 3;
493                         } else {
494                             this.viewmode = 1;
495                         }
496                         e.currentTarget.addClass('checked')
497                         this.render();
498                         this.filemanager.one('.fp-content').setAttribute('tabIndex', '0');
499                         this.filemanager.one('.fp-content').focus();
500                         this.set_preference('recentviewmode', this.viewmode);
501                     }
502                 }, this);
503         },
505         show_filepicker: function (e) {
506             // if maxfiles == -1, the no limit
507             e.preventDefault();
508             if (this.is_disabled()) {
509                 return;
510             }
511             var options = this.filepicker_options;
512             options.formcallback = this.filepicker_callback;
513             // XXX: magic here, to let filepicker use filemanager scope
514             options.magicscope = this;
515             options.savepath = this.currentpath;
516             options.previousActiveElement = e.target.ancestor('a', true);
517             M.core_filepicker.show(Y, options);
518         },
520         print_path: function() {
521             var p = this.options.path;
522             this.pathbar.setContent('').addClass('empty');
523             if (p && p.length!=0 && this.viewmode != 2) {
524                 for(var i = 0; i < p.length; i++) {
525                     var el = this.pathnode.cloneNode(true);
526                     this.pathbar.appendChild(el);
528                     if (i == 0) {
529                         el.addClass('first');
530                     }
531                     if (i == p.length-1) {
532                         el.addClass('last');
533                     }
535                     if (i%2) {
536                         el.addClass('even');
537                     } else {
538                         el.addClass('odd');
539                     }
540                     el.one('.fp-path-folder-name').setContent(Y.Escape.html(p[i].name)).
541                         on('click', function(e, path) {
542                             e.preventDefault();
543                             if (!this.is_disabled()) {
544                                 this.refresh(path);
545                             }
546                         }, this, p[i].path);
547                 }
548                 this.pathbar.removeClass('empty');
549             }
550         },
551         get_filepath: function(obj) {
552             if (obj.path && obj.path.length) {
553                 return obj.path[obj.path.length-1].path;
554             }
555             return '';
556         },
557         treeview_dynload: function(node, cb) {
558             var retrieved_children = {};
559             if (node.children) {
560                 for (var i in node.children) {
561                     retrieved_children[node.children[i].path] = node.children[i];
562                 }
563             }
564             if (!node.path || node.path == '/') {
565                 // this is a root pseudo folder
566                 node.fileinfo.filepath = '/';
567                 node.fileinfo.type = 'folder';
568                 node.fileinfo.fullname = node.fileinfo.title;
569                 node.fileinfo.filename = '.';
570             }
571             this.request({
572                 action:'list',
573                 params: {filepath:node.path?node.path:''},
574                 scope:this,
575                 callback: function(id, obj, args) {
576                     var list = obj.list;
577                     var scope = args.scope;
578                     // check that user did not leave the view mode before recieving this response
579                     if (!(scope.viewmode == 2 && node && node.getChildrenEl())) {
580                         return;
581                     }
582                     if (cb != null) { // (in manual mode do not update current path)
583                         scope.options = obj;
584                         scope.currentpath = node.path?node.path:'/';
585                     }
586                     node.highlight(false);
587                     node.origlist = obj.list ? obj.list : null;
588                     node.origpath = obj.path ? obj.path : null;
589                     node.children = [];
590                     for(k in list) {
591                         if (list[k].type == 'folder' && retrieved_children[list[k].filepath]) {
592                             // if this child is a folder and has already been retrieved
593                             retrieved_children[list[k].filepath].fileinfo = list[k];
594                             node.children[node.children.length] = retrieved_children[list[k].filepath];
595                         } else {
596                             // append new file to the list
597                             scope.view_files([list[k]]);
598                         }
599                     }
600                     if (cb == null) {
601                         node.refresh();
602                     } else {
603                         // invoke callback requested by TreeView component
604                         cb();
605                     }
606                     scope.content_scrolled();
607                 }
608             }, false);
609         },
610         content_scrolled: function(e) {
611             setTimeout(Y.bind(function() {
612                 if (this.processingimages) {return;}
613                 this.processingimages = true;
614                 var scope = this,
615                     fpcontent = this.filemanager.one('.fp-content'),
616                     fpcontenty = fpcontent.getY(),
617                     fpcontentheight = fpcontent.getStylePx('height'),
618                     is_node_visible = function(node) {
619                         var offset = node.getY()-fpcontenty;
620                         if (offset <= fpcontentheight && (offset >=0 || offset+node.getStylePx('height')>=0)) {
621                             return true;
622                         }
623                         return false;
624                     };
625                 // replace src for visible images that need to be lazy-loaded
626                 if (scope.lazyloading) {
627                     fpcontent.all('img').each( function(node) {
628                         if (node.get('id') && scope.lazyloading[node.get('id')] && is_node_visible(node)) {
629                             node.setImgRealSrc(scope.lazyloading);
630                         }
631                     });
632                 }
633                 this.processingimages = false;
634             }, this), 200)
635         },
636         view_files: function(appendfiles, actionfiles) {
637             this.filemanager.removeClass('fm-updating').removeClass('fm-noitems');
638             if ((appendfiles == null) && (!this.options.list || this.options.list.length == 0) && this.viewmode != 2) {
639                 this.filemanager.addClass('fm-noitems');
640                 // This is used to focus after refreshing the list files is empty by deletion file action.
641                 if (actionfiles !== undefined && actionfiles.action == 'delete') {
642                     this.filemanager.one('.fp-btn-add a').focus();
643                 }
644                 return;
645             }
646             var list = (appendfiles != null) ? appendfiles : this.options.list;
647             var element_template;
648             if (this.viewmode == 2 || this.viewmode == 3) {
649                 element_template = Y.Node.create(M.form_filemanager.templates.listfilename);
650             } else {
651                 this.viewmode = 1;
652                 element_template = Y.Node.create(M.form_filemanager.templates.iconfilename);
653             }
655             if (this.viewmode == 1 || this.viewmode == 2) {
656                 this.filemanager.one('.fp-btn-delete').addClass('d-none');
657             } else {
658                 this.filemanager.one('.fp-btn-delete').removeClass('d-none');
659             }
660             var options = {
661                 viewmode : this.viewmode,
662                 appendonly : appendfiles != null,
663                 filenode : element_template,
664                 disablecheckboxes: false,
665                 callbackcontext : this,
666                 callback : function(e, node) {
667                     if (e.preventDefault) { e.preventDefault(); }
668                     if (node.type == 'folder') {
669                         this.refresh(node.filepath);
670                     } else {
671                         // This is used to focus on file after dialogue closed.
672                         var previousActiveElement = e.target.ancestor('a', true);
673                         this.options.previousActiveElement = previousActiveElement;
674                         this.selectui.set('focusOnPreviousTargetAfterHide', true);
675                         this.selectui.set('focusAfterHide', previousActiveElement);
676                         this.select_file(node);
677                     }
678                 },
679                 rightclickcallback : function(e, node) {
680                     if (e.preventDefault) { e.preventDefault(); }
681                     this.select_file(node);
682                 },
683                 classnamecallback : function(node) {
684                     var classname = '';
685                     if (node.type == 'folder' || (!node.type && !node.filename)) {
686                         classname = classname + ' fp-folder';
687                     }
688                     if (node.filename || node.filepath || (node.path && node.path != '/')) {
689                         classname = classname + ' fp-hascontextmenu';
690                     }
691                     if (node.isref) {
692                         classname = classname + ' fp-isreference';
693                     }
694                     if (node.refcount) {
695                         classname = classname + ' fp-hasreferences';
696                     }
697                     if (node.originalmissing) {
698                         classname = classname + ' fp-originalmissing';
699                     }
700                     if (node.sortorder == 1) { classname = classname + ' fp-mainfile';}
701                     return Y.Lang.trim(classname);
702                 }
703             };
704             if (this.viewmode == 2) {
705                 options.dynload = true;
706                 options.filepath = this.options.path;
707                 options.treeview_dynload = this.treeview_dynload;
708                 options.norootrightclick = true;
709                 options.callback = function(e, node) {
710                     // TODO MDL-32736 e is not an event here but an object with properties 'event' and 'node'
711                     if (!node.fullname) {return;}
712                     if (node.type != 'folder') {
713                         if (e.node.parent && e.node.parent.origpath) {
714                             // set the current path
715                             this.options.path = e.node.parent.origpath;
716                             this.options.list = e.node.parent.origlist;
717                             this.print_path();
718                         }
719                         this.currentpath = node.filepath;
720                         var previousActiveElement = Y.Node(e.event.target).ancestor('a', true);
721                         this.options.previousActiveElement = previousActiveElement;
722                         this.selectui.set('focusOnPreviousTargetAfterHide', true);
723                         this.selectui.set('focusAfterHide', previousActiveElement);
724                         this.select_file(node);
725                     } else {
726                         // save current path and filelist (in case we want to jump to other viewmode)
727                         this.options.path = e.node.origpath;
728                         this.options.list = e.node.origlist;
729                         this.currentpath = node.filepath;
730                         this.print_path();
731                         //this.content_scrolled();
732                     }
733                 };
734             }
735             if (!this.lazyloading) {
736                 this.lazyloading={};
737             }
738             this.filemanager.one('.fp-content').fp_display_filelist(options, list, this.lazyloading);
739             if (this.viewmode != 2) {
740                 this.content_scrolled();
741             }
742             // This is used to focus after refreshing the list files by update file and set main file action.
743             if (actionfiles !== undefined) {
744                 if (actionfiles.action == 'updatefile' || actionfiles.action == 'setmainfile') {
745                     var fileslist = this.filemanager.one('.fp-content');
746                     fileslist.all('a').each(function(parentnode) {
747                         parentnode.all('.fp-filename').each(function(childnode) {
748                             if (childnode.get('innerHTML') == actionfiles.newfilename) {
749                                 parentnode.focus();
750                             }
751                         });
752                     });
753                 }
754                 if (actionfiles.action == 'delete') {
755                     this.filemanager.one('.fp-btn-delete a').focus();
756                 }
757             }
758         },
759         populateLicensesSelect: function(licensenode, filenode) {
760             if (!licensenode) {
761                 return;
762             }
763             licensenode.setContent('');
764             var selectedlicense = this.filepicker_options.defaultlicense;
765             if (filenode) {
766                 // File has a license already, use it.
767                 selectedlicense = filenode.license;
768             } else if (this.filepicker_options.rememberuserlicensepref && this.get_preference('recentlicense')) {
769                 // When 'Remember user licence preference' is enabled use the last license selected by the user, if any.
770                 selectedlicense = this.get_preference('recentlicense');
771             }
772             var licenses = this.filepicker_options.licenses;
773             for (var i in licenses) {
774                 // Include the file's current license, even if not enabled, to prevent displaying
775                 // misleading information about which license the file currently has assigned to it.
776                 if (licenses[i].enabled == true || (filenode !== undefined && licenses[i].shortname === filenode.license)) {
777                     var option = Y.Node.create('<option/>').
778                     set('selected', (licenses[i].shortname == selectedlicense)).
779                     set('value', licenses[i].shortname).
780                     setContent(Y.Escape.html(licenses[i].fullname));
781                     licensenode.appendChild(option);
782                 }
783             }
784         },
785         set_current_tree: function(tree) {
786             var appendfilepaths = function(list, node) {
787                 if (!node || !node.children || !node.children.length) {return;}
788                 for (var i in node.children) {
789                     list[list.length] = node.children[i].filepath;
790                     appendfilepaths(list, node.children[i]);
791                 }
792             }
793             var list = ['/'];
794             appendfilepaths(list, tree);
795             var selectnode = this.selectnode;
796             node = selectnode.one('.fp-path select');
797             node.setContent('');
798             for (var i in list) {
799                 node.appendChild(Y.Node.create('<option/>').
800                     set('value', list[i]).setContent(Y.Escape.html(list[i])));
801             }
802         },
803         update_file: function(confirmed) {
804             var selectnode = this.selectnode;
805             var fileinfo = this.selectui.fileinfo;
807             var newfilename = Y.Lang.trim(selectnode.one('.fp-saveas input').get('value'));
808             var filenamechanged = (newfilename && newfilename != fileinfo.fullname);
809             var pathselect = selectnode.one('.fp-path select'),
810                     pathindex = pathselect.get('selectedIndex'),
811                     targetpath = pathselect.get("options").item(pathindex).get('value');
812             var filepathchanged = (targetpath != this.get_parent_folder_name(fileinfo));
813             var newauthor = Y.Lang.trim(selectnode.one('.fp-author input').get('value'));
814             var authorchanged = (newauthor != Y.Lang.trim(fileinfo.author));
815             var licenseselect = selectnode.one('.fp-license select'),
816                     licenseindex = licenseselect.get('selectedIndex'),
817                     newlicense = licenseselect.get("options").item(licenseindex).get('value');
818             var licensechanged = (newlicense != fileinfo.license);
820             var params, action;
821             var dialog_options = {callback:this.update_file, callbackargs:[true], scope:this};
822             if (fileinfo.type == 'folder') {
823                 if (!newfilename) {
824                     this.print_msg(M.util.get_string('entername', 'repository'), 'error');
825                     return;
826                 }
827                 if (filenamechanged || filepathchanged) {
828                     if (!confirmed) {
829                         dialog_options.message = M.util.get_string('confirmrenamefolder', 'repository');
830                         this.show_confirm_dialog(dialog_options);
831                         return;
832                     }
833                     params = {filepath:fileinfo.filepath, newdirname:newfilename, newfilepath:targetpath};
834                     action = 'updatedir';
835                 }
836             } else {
837                 if (!newfilename) {
838                     this.print_msg(M.util.get_string('enternewname', 'repository'), 'error');
839                     return;
840                 }
842                 if ((filenamechanged || filepathchanged) && !confirmed) {
843                     var warnings = '';
844                     var originalfilenamearr = fileinfo.fullname.split('.');
845                     var originalextension = (originalfilenamearr.length > 1) ? originalfilenamearr.pop() : "";
846                     var newfilenamearr = newfilename.split('.');
847                     var newextension = (newfilenamearr.length > 1) ? newfilenamearr.pop() : "";
849                     if (newextension !== originalextension) {
850                         if (newextension === "") {
851                             var string = M.util.get_string('originalextensionremove', 'repository', originalextension);
852                         } else {
853                             var stringvars = {
854                                 originalextension: originalextension,
855                                 newextension: newextension
856                             }
857                             string = M.util.get_string('originalextensionchange', 'repository', stringvars);
858                         }
859                         warnings = warnings.concat('<li>', string, '</li>');
860                     }
861                     if (fileinfo.refcount) {
862                         var string = M.util.get_string('aliaseschange', 'repository', fileinfo.refcount);
863                         warnings = warnings.concat('<li>', string, '</li>');
864                     }
865                     if (warnings.length > 0) {
866                         var message = '';
867                         var confirmmsg = M.util.get_string('confirmrenamefile', 'repository', fileinfo.refcount);
868                         dialog_options.message = message.concat('<p>', confirmmsg, '</p>',
869                             '<ul class="px-5">', warnings, '</ul>');
870                         this.show_confirm_dialog(dialog_options);
871                         return;
872                     }
873                 }
874                 if (filenamechanged || filepathchanged || licensechanged || authorchanged) {
875                     params = {filepath:fileinfo.filepath, filename:fileinfo.fullname,
876                         newfilename:newfilename, newfilepath:targetpath,
877                         newlicense:newlicense, newauthor:newauthor};
878                     action = 'updatefile';
879                 }
880             }
881             if (!action) {
882                 // no changes
883                 this.selectui.hide();
884                 return;
885             }
886             selectnode.addClass('loading');
887             this.request({
888                 action: action,
889                 scope: this,
890                 params: params,
891                 callback: function(id, obj, args) {
892                     if (obj.error) {
893                         selectnode.removeClass('loading');
894                         args.scope.print_msg(obj.error, 'error');
895                     } else {
896                         args.scope.selectui.hide();
897                         var actionfile = {action: action, newfilename: newfilename};
898                         args.scope.refresh((obj && obj.filepath) ? obj.filepath : '/', actionfile);
899                         M.form_filemanager.formChangeChecker.markFormChangedFromNode(this.scope.filemanager.getDOMNode());
900                     }
901                 }
902             });
903         },
904         /**
905          * Displays a confirmation dialog
906          * Expected attributes in dialog_options: message, callback, callbackargs(optional), scope(optional)
907          */
908         show_confirm_dialog: function(dialog_options) {
909             // instead of M.util.show_confirm_dialog(e, dialog_options);
910             if (!this.confirm_dlg) {
911                 this.confirm_dlg_node = Y.Node.create(M.form_filemanager.templates.confirmdialog);
912                 var node = this.confirm_dlg_node;
913                 node.generateID();
914                 this.confirm_dlg = new M.core.dialogue({
915                     draggable    : true,
916                     bodyContent  : node,
917                     centered     : true,
918                     modal        : true,
919                     visible      : false,
920                     buttons      : {},
921                 });
922                 var handle_confirm = function(ev) {
923                     var dlgopt = this.confirm_dlg.dlgopt;
924                     ev.preventDefault();
925                     this.confirm_dlg.hide();
926                     if (dlgopt.callback) {
927                         if (dlgopt.callbackargs) {
928                             dlgopt.callback.apply(dlgopt.scope || this, dlgopt.callbackargs);
929                         } else {
930                             dlgopt.callback.apply(dlgopt.scope || this);
931                         }
932                     }
933                 }
934                 var handle_cancel = function(ev) {
935                     ev.preventDefault();
936                     this.confirm_dlg.hide();
937                 }
938                 node.one('.fp-dlg-butconfirm').on('click', handle_confirm, this);
939                 node.one('.fp-dlg-butcancel').on('click', handle_cancel, this);
940             }
941             // This used to focus on before active element after confirm dialogue closed.
942             if (typeof dialog_options.previousActiveElement != 'undefined') {
943                 this.confirm_dlg.set('focusAfterHide', dialog_options.previousActiveElement);
944             }
945             this.confirm_dlg.dlgopt = dialog_options;
946             if (typeof dialog_options.header != 'undefined') {
947                 this.confirm_dlg.set('headerContent', dialog_options.header);
948             }
949             this.confirm_dlg_node.one('.fp-dlg-text').setContent(dialog_options.message);
950             this.confirm_dlg.show();
951         },
952         setup_select_file: function() {
953             var selectnode = this.selectnode;
954             var scope = this;
955             // bind labels with corresponding inputs
956             selectnode.all('.fp-saveas,.fp-path,.fp-author,.fp-license').each(function (node) {
957                 node.all('label').set('for', node.one('input,select').generateID());
958             });
959             // register event on clicking buttons
960             selectnode.one('.fp-file-update').on('click', function(e) {
961                 e.preventDefault();
962                 this.update_file();
963             }, this);
964             selectnode.all('form input').on('key', function(e) {
965                 e.preventDefault();
966                 scope.update_file();
967             }, 'enter');
968             selectnode.one('.fp-file-download').on('click', function(e) {
969                 e.preventDefault();
970                 if (this.selectui.fileinfo.type != 'folder') {
971                     node = Y.Node.create('<iframe></iframe>').setStyles({
972                         visibility : 'hidden',
973                         width : '1px',
974                         height : '1px'
975                     });
976                     node.set('src', this.selectui.fileinfo.url);
977                     Y.one('body').appendChild(node);
978                 }
979             }, this);
980             selectnode.one('.fp-file-delete').on('click', function(e) {
981                 e.preventDefault();
982                 var dialog_options = {
983                     scope: this,
984                     header: M.util.get_string('confirm', 'moodle'),
985                 };
986                 var params = {};
987                 var fileinfo = this.selectui.fileinfo;
988                 params.filepath = fileinfo.filepath;
989                 if (fileinfo.type == 'folder') {
990                     params.filename = '.';
991                     dialog_options.message = M.util.get_string('confirmdeletefolder', 'repository');
992                 } else {
993                     params.filename = fileinfo.fullname;
994                     if (fileinfo.refcount) {
995                         dialog_options.message = M.util.get_string('confirmdeletefilewithhref', 'repository', fileinfo.refcount);
996                     } else {
997                         dialog_options.message = M.util.get_string('confirmdeletefile', 'repository');
998                     }
999                 }
1000                 dialog_options.callbackargs = [params];
1001                 dialog_options.callback = function(params) {
1002                     //selectnode.addClass('loading');
1003                     this.request({
1004                         action: 'delete',
1005                         scope: this,
1006                         params: params,
1007                         callback: function(id, obj, args) {
1008                             //args.scope.selectui.hide();
1009                             args.scope.filecount--;
1010                             args.scope.refresh(obj.filepath, {action: 'delete'});
1011                             M.form_filemanager.formChangeChecker.markFormChangedFromNode(this.scope.filemanager.getDOMNode());
1013                             require(['core_form/events'], function(FormEvent) {
1014                                 FormEvent.notifyUploadChanged(this.scope.filemanager.get('id'));
1015                             }.bind(this));
1016                         }
1017                     });
1018                 };
1019                 this.selectui.hide(); // TODO remove this after confirm dialog is replaced with YUI3
1020                 // This is used to focus on before active element after confirm dialogue closed.
1021                 if (this.options.previousActiveElement !== undefined) {
1022                     dialog_options.previousActiveElement = this.options.previousActiveElement;
1023                 }
1024                 this.show_confirm_dialog(dialog_options);
1025             }, this);
1026             selectnode.one('.fp-file-zip').on('click', function(e) {
1027                 e.preventDefault();
1028                 var params = {};
1029                 var fileinfo = this.selectui.fileinfo;
1030                 if (fileinfo.type != 'folder') {
1031                     // this button should not even be shown
1032                     return;
1033                 }
1034                 params['filepath']   = fileinfo.filepath;
1035                 params['filename']   = '.';
1036                 selectnode.addClass('loading');
1037                 this.request({
1038                     action: 'zip',
1039                     scope: this,
1040                     params: params,
1041                     callback: function(id, obj, args) {
1042                         args.scope.selectui.hide();
1043                         args.scope.refresh(obj.filepath);
1044                     }
1045                 });
1046             }, this);
1047             selectnode.one('.fp-file-unzip').on('click', function(e) {
1048                 e.preventDefault();
1049                 var params = {};
1050                 var fileinfo = this.selectui.fileinfo;
1051                 if (fileinfo.type != 'zip') {
1052                     // this button should not even be shown
1053                     return;
1054                 }
1055                 params['filepath'] = fileinfo.filepath;
1056                 params['filename'] = fileinfo.fullname;
1057                 // The unlimited value of areamaxbytes is -1, it is defined by FILE_AREA_MAX_BYTES_UNLIMITED.
1058                 params['areamaxbytes'] = this.areamaxbytes ? this.areamaxbytes : -1;
1059                 selectnode.addClass('loading');
1060                 this.request({
1061                     action: 'unzip',
1062                     scope: this,
1063                     params: params,
1064                     callback: function(id, obj, args) {
1065                         if (obj.error) {
1066                             selectnode.removeClass('loading');
1067                             args.scope.print_msg(obj.error, 'error');
1068                         } else {
1069                             args.scope.selectui.hide();
1070                             args.scope.refresh(obj.filepath);
1071                         }
1072                     }
1073                 });
1074             }, this);
1075             selectnode.one('.fp-file-setmain').on('click', function(e) {
1076                 e.preventDefault();
1077                 var params = {};
1078                 var fileinfo = this.selectui.fileinfo;
1079                 if (!this.enablemainfile || fileinfo.type == 'folder') {
1080                     // this button should not even be shown for folders or when mainfile is disabled
1081                     return;
1082                 }
1083                 params['filepath'] = fileinfo.filepath;
1084                 params['filename'] = fileinfo.fullname;
1085                 selectnode.addClass('loading');
1086                 this.request({
1087                     action: 'setmainfile',
1088                     scope: this,
1089                     params: params,
1090                     callback: function(id, obj, args) {
1091                         args.scope.selectui.hide();
1092                         var actionfile = {action: 'setmainfile', newfilename: fileinfo.fullname};
1093                         args.scope.refresh(fileinfo.filepath, actionfile);
1094                     }
1095                 });
1096             }, this);
1097             selectnode.all('.fp-file-cancel').on('click', function(e) {
1098                 e.preventDefault();
1099                 // TODO if changed asked to confirm, the same with close button
1100                 this.selectui.hide();
1101             }, this);
1102             selectnode.all('.fp-file-update, .fp-file-download, .fp-file-delete, .fp-file-zip, .fp-file-unzip, ' +
1103                 '.fp-file-setmain, .fp-file-cancel').on('key', function(e) {
1104                     e.preventDefault();
1105                     this.simulate('click');
1106             }, 'enter');
1107         },
1108         get_parent_folder_name: function(node) {
1109             if (node.type != 'folder' || node.filepath.length < node.fullname.length+1) {
1110                 return node.filepath;
1111             }
1112             var basedir = node.filepath.substr(0, node.filepath.length - node.fullname.length - 1);
1113             var lastdir = node.filepath.substr(node.filepath.length - node.fullname.length - 2);
1114             if (lastdir == '/' + node.fullname + '/') {
1115                 return basedir;
1116             }
1117             return node.filepath;
1118         },
1119         select_file: function(node) {
1120             if (this.is_disabled()) {
1121                 return;
1122             }
1123             var selectnode = this.selectnode;
1124             selectnode.removeClass('loading').removeClass('fp-folder').
1125                 removeClass('fp-file').removeClass('fp-zip').removeClass('fp-cansetmain');
1126             if (node.type == 'folder' || node.type == 'zip') {
1127                 selectnode.addClass('fp-'+node.type);
1128             } else {
1129                 selectnode.addClass('fp-file');
1130             }
1131             if (this.enablemainfile && (node.sortorder != 1) && node.type == 'file') {
1132                 selectnode.addClass('fp-cansetmain');
1133             }
1134             this.selectui.fileinfo = node;
1135             selectnode.one('.fp-saveas input').set('value', node.fullname);
1136             var foldername = this.get_parent_folder_name(node);
1137             selectnode.all('.fp-author input').set('value', node.author ? node.author : '');
1138             this.populateLicensesSelect(selectnode.one('.fp-license select'), node);
1139             selectnode.all('.fp-path select option[selected]').set('selected', false);
1140             selectnode.all('.fp-path select option').each(function(el){
1141                 if (el.get('value') == foldername) {
1142                     el.set('selected', true);
1143                 }
1144             });
1145             selectnode.all('.fp-author input, .fp-license select').set('disabled',(node.type == 'folder')?'disabled':'');
1146             // display static information about a file (when known)
1147             var attrs = ['datemodified','datecreated','size','dimensions','original','reflist'];
1148             for (var i in attrs) {
1149                 if (selectnode.one('.fp-'+attrs[i])) {
1150                     var value = (node[attrs[i]+'_f']) ? node[attrs[i]+'_f'] : (node[attrs[i]] ? node[attrs[i]] : '');
1151                     // Escape if the attribute being evaluated is not for the list of reference files.
1152                     if (attrs[i] !== 'reflist') {
1153                         value = Y.Escape.html(value);
1154                     }
1155                     selectnode.one('.fp-'+attrs[i]).addClassIf('fp-unknown', ''+value == '')
1156                         .one('.fp-value').setContent(value);
1157                 }
1158             }
1159             // display thumbnail
1160             var imgnode = Y.Node.create('<img/>').
1161                 set('src', node.realthumbnail ? node.realthumbnail : node.thumbnail).
1162                 setStyle('maxHeight', ''+(node.thumbnail_height ? node.thumbnail_height : 90)+'px').
1163                 setStyle('maxWidth', ''+(node.thumbnail_width ? node.thumbnail_width : 90)+'px');
1164             selectnode.one('.fp-thumbnail').setContent('').appendChild(imgnode);
1165             // load original location if applicable
1166             if (node.isref && !node.original) {
1167                 selectnode.one('.fp-original').removeClass('fp-unknown').addClass('fp-loading');
1168                 this.request({
1169                     action: 'getoriginal',
1170                     scope: this,
1171                     params: {'filepath':node.filepath,'filename':node.fullname},
1172                     callback: function(id, obj, args) {
1173                         // check if we did not select another file meanwhile
1174                         var scope = args.scope;
1175                         if (scope.selectui.fileinfo && node &&
1176                                 scope.selectui.fileinfo.filepath == node.filepath &&
1177                                 scope.selectui.fileinfo.fullname == node.fullname) {
1178                             selectnode.one('.fp-original').removeClass('fp-loading');
1179                             if (obj.original) {
1180                                 node.original = obj.original;
1181                                 selectnode.one('.fp-original .fp-value').setContent(Y.Escape.html(node.original));
1182                             } else {
1183                                 selectnode.one('.fp-original .fp-value').setContent(M.util.get_string('unknownsource', 'repository'));
1184                             }
1185                         }
1186                     }
1187                 }, false);
1188             }
1189             // load references list if applicable
1190             selectnode.one('.fp-refcount').setContent(node.refcount ? M.util.get_string('referencesexist', 'repository', node.refcount) : '');
1191             if (node.refcount && !node.reflist) {
1192                 selectnode.one('.fp-reflist').removeClass('fp-unknown').addClass('fp-loading');
1193                 this.request({
1194                     action: 'getreferences',
1195                     scope: this,
1196                     params: {'filepath':node.filepath,'filename':node.fullname},
1197                     callback: function(id, obj, args) {
1198                         // check if we did not select another file meanwhile
1199                         var scope = args.scope;
1200                         if (scope.selectui.fileinfo && node &&
1201                                 scope.selectui.fileinfo.filepath == node.filepath &&
1202                                 scope.selectui.fileinfo.fullname == node.fullname) {
1203                             selectnode.one('.fp-reflist').removeClass('fp-loading');
1204                             if (obj.references) {
1205                                 node.reflist = '';
1206                                 for (var i in obj.references) {
1207                                     node.reflist += '<li>'+Y.Escape.html(obj.references[i])+'</li>';
1208                                 }
1209                                 selectnode.one('.fp-reflist .fp-value').setContent(node.reflist);
1210                             } else {
1211                                 selectnode.one('.fp-reflist .fp-value').setContent('');
1212                             }
1213                         }
1214                     }
1215                 }, false);
1216             }
1217             // update dialog header
1218             var nodename = node.fullname;
1219             // Limit the string length so it fits nicely on mobile devices
1220             var namelength = 50;
1221             if (nodename.length > namelength) {
1222                 nodename = nodename.substring(0, namelength) + '...';
1223             }
1224             Y.one('#fm-dialog-label_'+selectnode.get('id')).setContent(Y.Escape.html(M.util.get_string('edit', 'moodle')+' '+nodename));
1225             // show panel
1226             this.selectui.show();
1227             Y.one('#'+selectnode.get('id')).focus();
1228         },
1229         render: function(obj, action) {
1230             this.print_path();
1231             this.view_files(null, action);
1232         },
1233         has_folder: function(foldername) {
1234             var element;
1235             for (var i in this.options.list) {
1236                 element = this.options.list[i];
1237                 if (element.type == 'folder' && element.fullname == foldername) {
1238                     return true;
1239                 }
1240             }
1241             return false;
1242         },
1243         get_preference: function(name) {
1244             if (this.userprefs[name]) {
1245                 return this.userprefs[name];
1246             } else {
1247                 return false;
1248             }
1249         },
1250         set_preference: function(name, value) {
1251             if (this.userprefs[name] != value) {
1252                 M.util.set_user_preference('filemanager_' + name, value);
1253                 this.userprefs[name] = value;
1254             }
1255         },
1256     });
1258     // finally init everything needed
1259     // hide loading picture, display filemanager interface
1260     var filemanager = Y.one('#filemanager-'+options.client_id);
1261     filemanager.removeClass('fm-loading').addClass('fm-loaded');
1263     var manager = new FileManagerHelper(options);
1264     var dndoptions = {
1265         filemanager: manager,
1266         acceptedtypes: options.filepicker.accepted_types,
1267         clientid: options.client_id,
1268         author: options.author,
1269         maxfiles: options.maxfiles,
1270         maxbytes: options.maxbytes,
1271         areamaxbytes: options.areamaxbytes,
1272         itemid: options.itemid,
1273         repositories: manager.filepicker_options.repositories,
1274         containerid: manager.dndcontainer.get('id'),
1275         contextid: options.context.id
1276     };
1277     M.form_dndupload.init(Y, dndoptions);