Proyectos de Subversion Moodle

Rev

Rev 11 | | Comparar con el anterior | Ultima modificación | Ver Log |

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