MDL-27829 block creation - ensure correct pagetypepattern in mod/ pages
[moodle.git] / repository / filepicker.js
blob5d2fa6daf69f161c0d57737fa5671267c5a19d97
1 // YUI3 File Picker module for moodle
2 // Author: Dongsheng Cai <dongsheng@moodle.com>
4 /**
5  *
6  * File Picker UI
7  * =====
8  * this.rendered, it tracks if YUI Panel rendered
9  * this.api, stores the URL to make ajax request
10  * this.mainui, YUI Panel
11  * this.treeview, YUI Treeview
12  * this.viewbar, a button group to switch view mode
13  * this.viewmode, store current view mode
14  *
15  * Filepicker options:
16  * =====
17  * this.options.client_id, the instance id
18  * this.options.contextid
19  * this.options.itemid
20  * this.options.repositories, stores all repositories displaied in file picker
21  * this.options.formcallback
22  *
23  * Active repository options
24  * =====
25  * this.active_repo.id
26  * this.active_repo.nosearch
27  * this.active_repo.norefresh
28  * this.active_repo.nologin
29  * this.active_repo.help
30  * this.active_repo.manage
31  *
32  * Server responses
33  * =====
34  * this.filelist, cached filelist
35  * this.pages
36  * this.page
37  * this.filepath, current path
38  * this.logindata, cached login form
39  */
41 M.core_filepicker = M.core_filepicker || {};
43 /**
44  * instances of file pickers used on page
45  */
46 M.core_filepicker.instances = M.core_filepicker.instances || {};
47 M.core_filepicker.active_filepicker = null;
49 /**
50  * Init and show file picker
51  */
52 M.core_filepicker.show = function(Y, options) {
53     if (!M.core_filepicker.instances[options.client_id]) {
54         M.core_filepicker.init(Y, options);
55     }
56     M.core_filepicker.instances[options.client_id].show();
59 /**
60  * Add new file picker to current instances
61  */
62 M.core_filepicker.init = function(Y, options) {
63     var FilePickerHelper = function(options) {
64         FilePickerHelper.superclass.constructor.apply(this, arguments);
65     };
67     FilePickerHelper.NAME = "FilePickerHelper";
68     FilePickerHelper.ATTRS = {
69         options: {},
70         lang: {}
71     };
73     Y.extend(FilePickerHelper, Y.Base, {
74         api: M.cfg.wwwroot+'/repository/repository_ajax.php',
76         initializer: function(options) {
77             this.options = options;
78             if (!this.options.savepath) {
79                 this.options.savepath = '/';
80             }
81         },
83         destructor: function() {
84         },
86         request: function(args, redraw) {
87             var client_id = args.client_id;
88             if (!args.api) {
89                 var api = this.api + '?action='+args.action;
90             } else {
91                 var api = args.api + '?action='+args.action;
92             }
93             var params = {};
94             var scope = this;
95             if (args['scope']) {
96                 scope = args['scope'];
97             }
98             params['repo_id']=args.repository_id;
99             params['p'] = args.path?args.path:'';
100             params['page'] = args.page?args.page:'';
101             params['env']=this.options.env;
102             // the form element only accept certain file types
103             params['accepted_types']=this.options.accepted_types;
104             params['sesskey'] = M.cfg.sesskey;
105             params['client_id'] = args.client_id;
106             params['itemid'] = this.options.itemid?this.options.itemid:0;
107             params['maxbytes'] = this.options.maxbytes?this.options.maxbytes:-1;
108             if (this.options.context && this.options.context.id) {
109                 params['ctx_id'] = this.options.context.id;
110             }
111             if (args['params']) {
112                 for (i in args['params']) {
113                     params[i] = args['params'][i];
114                 }
115             }
116             if (args.action == 'upload') {
117                 var list = [];
118                 for(var k in params) {
119                     var value = params[k];
120                     if(value instanceof Array) {
121                         for(var i in value) {
122                             list.push(k+'[]='+value[i]);
123                         }
124                     } else {
125                         list.push(k+'='+value);
126                     }
127                 }
128                 params = list.join('&');
129             } else {
130                 params = build_querystring(params);
131             }
132             var cfg = {
133                 method: 'POST',
134                 on: {
135                     complete: function(id,o,p) {
136                         var panel_id = '#panel-'+client_id;
137                         if (!o) {
138                             alert('IO FATAL');
139                             return;
140                         }
141                         var data = null;
142                         try {
143                             data = Y.JSON.parse(o.responseText);
144                         } catch(e) {
145                             scope.print_msg(M.str.repository.invalidjson, 'error');
146                             Y.one(panel_id).set('innerHTML', 'ERROR: '+M.str.repository.invalidjson+'<pre>'+stripHTML(o.responseText)+'</pre>');
147                             return;
148                         }
149                         // error checking
150                         if (data && data.error) {
151                             scope.print_msg(data.error, 'error');
152                             scope.list();
153                             return;
154                         } else if (data && data.event) {
155                             switch (data.event) {
156                                 case 'fileexists':
157                                     scope.process_existing_file(data);
158                                     break;
159                                 default:
160                                     break;
161                             }
162                         } else {
163                             if (data.msg) {
164                                 scope.print_msg(data.msg, 'info');
165                             }
166                             args.callback(id,data,p);
167                         }
168                     }
169                 },
170                 arguments: {
171                     scope: scope
172                 },
173                 headers: {
174                     'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
175                 },
176                 data: params,
177                 context: this
178             };
179             if (args.form) {
180                 cfg.form = args.form;
181             }
182             Y.io(api, cfg);
183             if (redraw) {
184                 this.wait('load');
185             }
186         },
187         process_existing_file: function(data) {
188             var scope = this;
189             var repository_id = scope.active_repo.id;
190             var client_id = scope.options.client_id;
191             var handleOverwrite = function() {
192                 // overwrite
193                 var dialog = this;
194                 var params = {}
195                 params['existingfilename'] = data.existingfile.filename;
196                 params['existingfilepath'] = data.existingfile.filepath;
197                 params['newfilename'] = data.newfile.filename;
198                 params['newfilepath'] = data.newfile.filepath;
199                 scope.request({
200                     'params': params,
201                     'scope': scope,
202                     'action':'overwrite',
203                     'path': '',
204                     'client_id': client_id,
205                     'repository_id': repository_id,
206                     'callback': function(id, o, args) {
207                         dialog.cancel();
208                         scope.hide();
209                         // editor needs to update url
210                         // filemanager do nothing
211                         if (scope.options.editor_target && scope.options.env == 'editor') {
212                             scope.options.editor_target.value = data.existingfile.url;
213                             scope.options.editor_target.onchange();
214                         }
215                     }
216                 }, true);
217             }
218             var handleRename = function() {
219                 if (scope.options.editor_target && scope.options.env == 'editor') {
220                     scope.options.editor_target.value = data.newfile.url;
221                     scope.options.editor_target.onchange();
222                 }
223                 this.cancel();
224                 scope.hide();
225                 data.client_id = client_id;
226                 var formcallback_scope = null;
227                 if (scope.options.magicscope) {
228                     formcallback_scope = scope.options.magicscope;
229                 } else {
230                     formcallback_scope = scope;
231                 }
232                 scope.options.formcallback.apply(formcallback_scope, [data]);
233             }
234             var handleCancel = function() {
235                 // Delete tmp file
236                 var dialog = this;
237                 var params = {};
238                 params['newfilename'] = data.newfile.filename;
239                 params['newfilepath'] = data.newfile.filepath;
240                 scope.request({
241                     'params': params,
242                     'scope': scope,
243                     'action':'deletetmpfile',
244                     'path': '',
245                     'client_id': client_id,
246                     'repository_id': repository_id,
247                     'callback': function(id, o, args) {
248                         scope.hide();
249                         dialog.cancel();
250                     }
251                 }, true);
252             }
253             var dialog = new YAHOO.widget.SimpleDialog("dlg", {
254                 width: "50em",
255                 fixedcenter: true,
256                 close: false,
257                 icon: YAHOO.widget.SimpleDialog.ICON_HELP,
258                 visible: true,
259                 zIndex: 9999993,
260                 draggable: true,
261                 buttons: [{ text: M.str.repository.overwrite, handler: handleOverwrite },
262                 { text: M.str.repository.renameto + ' "' + data.newfile.filename + '"', handler: handleRename },
263                 { text: M.str.moodle.cancel, handler: handleCancel, isDefault: true}]
264             });
265             dialog.setHeader(M.str.repository.fileexistsdialogheader);
266             if (scope.options.env == 'editor') {
267                 dialog.setBody(M.str.repository.fileexistsdialog_editor);
268             } else {
269                 dialog.setBody(M.str.repository.fileexistsdialog_filemanager);
270             }
272             dialog.render(document.body);
273             dialog.show();
274         },
275         print_msg: function(msg, type) {
276             var client_id = this.options.client_id;
277             var dlg_id = 'fp-msg-dlg-'+client_id;
278             function handleYes() {
279                 this.hide();
280             }
281             var icon = YAHOO.widget.SimpleDialog.ICON_INFO;
282             if (type=='error') {
283                 icon = YAHOO.widget.SimpleDialog.ICON_ALARM;
284             }
285             if (!this.msg_dlg) {
286                 this.msg_dlg = new YAHOO.widget.SimpleDialog(dlg_id,
287                      { width: "300px",
288                        fixedcenter: true,
289                        visible: true,
290                        draggable: true,
291                        close: true,
292                        text: msg,
293                        modal: false,
294                        icon: icon,
295                        zindex: 9999992,
296                        constraintoviewport: true,
297                        buttons: [{ text:M.str.moodle.ok, handler:handleYes, isDefault:true }]
298                      });
299                 this.msg_dlg.render(document.body);
300             } else {
301                 this.msg_dlg.setBody(msg);
302             }
303             var header = M.str.moodle.info;
304             if (type=='error') {
305                 header = M.str.moodle.error;
306             }
307             this.msg_dlg.setHeader(type);
308             this.msg_dlg.show();
309         },
310         build_tree: function(node, level) {
311             var client_id = this.options.client_id;
312             var dynload = this.active_repo.dynload;
313             if(node.children) {
314                 node.title = '<i><u>'+node.title+'</u></i>';
315             }
316             var info = {
317                 label:node.title,
318                 //title:fp_lang.date+' '+node.date+fp_lang.size+' '+node.size,
319                 filename:node.title,
320                 source:node.source?node.source:'',
321                 thumbnail:node.thumbnail,
322                 path:node.path?node.path:[]
323             };
324             var tmpNode = new YAHOO.widget.TextNode(info, level, false);
325             if(node.repo_id) {
326                 tmpNode.repo_id=node.repo_id;
327             }else{
328                 tmpNode.repo_id=this.active_repo.id;
329             }
330             if(node.children) {
331                 if(node.expanded) {
332                     tmpNode.expand();
333                 }
334                 if (dynload) {
335                     tmpNode.scope = this;
336                 }
337                 tmpNode.isLeaf = false;
338                 tmpNode.client_id = client_id;
339                 if (node.path) {
340                     tmpNode.path = node.path;
341                 } else {
342                     tmpNode.path = '';
343                 }
344                 for(var c in node.children) {
345                     this.build_tree(node.children[c], tmpNode);
346                 }
347             } else {
348                 tmpNode.isLeaf = true;
349             }
350         },
351         view_files: function(page) {
352             var p= page?page:null;
353             if (this.active_repo.issearchresult) {
354                 // list view is desiged to display treeview
355                 // it is not working well with search result
356                 this.view_as_icons();
357             } else {
358                 this.viewbar.set('disabled', false);
359                 if (this.viewmode == 1) {
360                     this.view_as_icons();
361                 } else if (this.viewmode == 2) {
362                     this.view_as_list(p);
363                 } else {
364                     this.view_as_icons();
365                 }
366             }
367         },
368         treeview_dynload: function(node, cb) {
369             var scope = node.scope;
370             var client_id = scope.options.client_id;
371             var repository_id = scope.active_repo.id;
372             scope.request({
373                 action:'list',
374                 client_id: client_id,
375                 repository_id: repository_id,
376                 path:node.path?node.path:'',
377                 page:node.page?args.page:'',
378                 callback: function(id, obj, args) {
379                     obj.issearchresult = false;
380                     var list = obj.list;
381                     scope.viewbar.set('disabled', false);
382                     scope.parse_repository_options(obj);
383                     for(k in list) {
384                         scope.build_tree(list[k], node);
385                     }
386                     cb();
387                 }
388             }, false);
389         },
390         view_as_list: function(p) {
391             var scope = this;
392             var page = null;
393             if (!p) {
394                 if (scope.active_repo.page) {
395                     page = scope.active_repo.page;
396                 }
397             } else {
398                 page = p;
399             }
400             scope.request({
401                 action:'list',
402                 client_id: scope.options.client_id,
403                 repository_id: scope.active_repo.id,
404                 path:'',
405                 page:page,
406                 callback: function(id, obj, args) {
407                     scope.parse_repository_options(obj);
408                     if (obj.login) {
409                         scope.viewbar.set('disabled', true);
410                         scope.print_login(obj);
411                         return;
412                     }
413                     var client_id = scope.options.client_id;
414                     var dynload = scope.active_repo.dynload;
415                     var list = obj.list;
416                     var panel_id = '#panel-'+client_id;
417                     scope.viewmode = 2;
418                     Y.one(panel_id).set('innerHTML', '');
420                     scope.print_header();
422                     var html = '<div class="fp-tree-panel" id="treeview-'+client_id+'">';
423                     if (list && list.length==0) {
424                         html += '<div class="fp-emptylist mdl-align">' +M.str.repository.nofilesavailable+'</div>';
425                     }
426                     html += '</div>';
428                     var tree = Y.Node.create(html);
429                     Y.one(panel_id).appendChild(tree);
430                     if (!list || list.length==0) {
431                         return;
432                     }
434                     scope.treeview = new YAHOO.widget.TreeView('treeview-'+client_id);
435                     if (dynload) {
436                         scope.treeview.setDynamicLoad(scope.treeview_dynload, 1);
437                     }
439                     for(k in list) {
440                         scope.build_tree(list[k], scope.treeview.getRoot());
441                     }
442                     scope.treeview.subscribe('clickEvent', function(e){
443                         if(e.node.isLeaf){
444                             var fileinfo = {};
445                             fileinfo['title'] = e.node.data.filename;
446                             fileinfo['source'] = e.node.data.source;
447                             fileinfo['thumbnail'] = e.node.data.thumbnail;
448                             scope.select_file(fileinfo);
449                         }
450                     });
451                     scope.treeview.draw();
452                 }
453             }, true);
454         },
455         view_as_icons: function() {
456             var scope = this;
457             var client_id = this.options.client_id;
458             var list = this.filelist;
459             var panel_id = '#panel-'+client_id;
460             this.viewmode = 1;
461             Y.one(panel_id).set('innerHTML', '');
463             this.print_header();
465             var html = '<div class="fp-grid-panel" id="fp-grid-panel-'+client_id+'">';
466             if (list && list.length==0) {
467                 html += '<div class="fp-emptylist mdl-align">' +M.str.repository.nofilesavailable+'</div>';
468             }
469             html += '</div>';
471             var gridpanel = Y.Node.create(html);
472             Y.one('#panel-'+client_id).appendChild(gridpanel);
473             var count = 0;
474             for(var k in list) {
475                 var node = list[k];
476                 var grid = document.createElement('DIV');
477                 grid.className='fp-grid';
478                 // the file name
479                 var title = document.createElement('DIV');
480                 title.id = 'grid-title-'+client_id+'-'+String(count);
481                 title.className = 'label';
482                 var filename = node.title;
483                 if (node.shorttitle) {
484                     filename = node.shorttitle;
485                 }
486                 var filename_id = 'filname-link-'+client_id+'-'+String(count);
487                 title.innerHTML += '<a href="###" id="'+filename_id+'" title="'+node.title+'"><span>'+filename+"</span></a>";
490                 if(node.thumbnail_width){
491                     grid.style.width = node.thumbnail_width+'px';
492                     title.style.width = (node.thumbnail_width-10)+'px';
493                 } else {
494                     grid.style.width = title.style.width = '90px';
495                 }
496                 var frame = document.createElement('DIV');
497                 frame.style.textAlign='center';
498                 if(node.thumbnail_height){
499                     frame.style.height = node.thumbnail_height+'px';
500                 }
501                 var img = document.createElement('img');
502                 img.src = node.thumbnail;
503                 img.title = node.title;
504                 if(node.thumbnail_alt) {
505                     img.alt = node.thumbnail_alt;
506                 }
507                 if(node.thumbnail_title) {
508                     img.title = node.thumbnail_title;
509                 }
511                 var link = document.createElement('A');
512                 link.href='###';
513                 link.id = 'img-id-'+client_id+'-'+String(count);
514                 if(node.url) {
515                     // hide
516                     //grid.innerHTML += '<p><a target="_blank" href="'+node.url+'">'+M.str.repository.preview+'</a></p>';
517                 }
518                 link.appendChild(img);
519                 frame.appendChild(link);
520                 grid.appendChild(frame);
521                 grid.appendChild(title);
522                 gridpanel.appendChild(grid);
524                 var y_title = Y.one('#'+title.id);
525                 var y_file = Y.one('#'+link.id);
526                 var dynload = this.active_repo.dynload;
527                 if(node.children) {
528                     y_file.on('click', function(e, p) {
529                         if(dynload) {
530                             var params = {'path':p.path};
531                             scope.list(params);
532                         }else{
533                             this.filelist = p.children;
534                             this.view_files();
535                         }
536                     }, this, node);
537                     y_title.on('click', function(e, p, id){
538                         var icon = Y.one(id);
539                         icon.simulate('click');
540                     }, this, node, '#'+link.id);
541                 } else {
542                     var fileinfo = {};
543                     fileinfo['title'] = list[k].title;
544                     fileinfo['source'] = list[k].source;
545                     fileinfo['thumbnail'] = list[k].thumbnail;
546                     fileinfo['haslicense'] = list[k].haslicense?true:false;
547                     fileinfo['hasauthor'] = list[k].hasauthor?true:false;
548                     y_title.on('click', function(e, args) {
549                         this.select_file(args);
550                     }, this, fileinfo);
551                     y_file.on('click', function(e, args) {
552                         this.select_file(args);
553                     }, this, fileinfo);
554                 }
555                 count++;
556             }
557         },
558         select_file: function(args) {
559             var client_id = this.options.client_id;
560             var thumbnail = Y.one('#fp-grid-panel-'+client_id);
561             if(thumbnail){
562                 thumbnail.setStyle('display', 'none');
563             }
564             var header = Y.one('#fp-header-'+client_id);
565             if (header) {
566                 header.setStyle('display', 'none');
567             }
568             var footer = Y.one('#fp-footer-'+client_id);
569             if (footer) {
570                 footer.setStyle('display', 'none');
571             }
572             var path = Y.one('#path-'+client_id);
573             if(path){
574                 path.setStyle('display', 'none');
575             }
576             var panel = Y.one('#panel-'+client_id);
577             var form_id = 'fp-rename-form-'+client_id;
578             var html = '<div class="fp-rename-form" id="'+form_id+'">';
579             html += '<p><img src="'+args.thumbnail+'" /></p>';
580             html += '<table width="100%">';
581             html += '<tr><td class="mdl-right"><label for="newname-'+client_id+'">'+M.str.repository.saveas+':</label></td>';
582             html += '<td class="mdl-left"><input type="text" id="newname-'+client_id+'" value="'+args.title+'" /></td></tr>';
584             var le_checked = '';
585             var le_style = '';
586             if (this.options.repositories[this.active_repo.id].return_types == 1) {
587                 // support external links only
588                 le_checked = 'checked';
589                 le_style = ' style="display:none;"';
590             } else if(this.options.repositories[this.active_repo.id].return_types == 2) {
591                 // support internal files only
592                 le_style = ' style="display:none;"';
593             }
594             if ((this.options.externallink && this.options.env == 'editor' && this.options.return_types != 1)) {
595                 html += '<tr'+le_style+'><td></td><td class="mdl-left"><input type="checkbox" id="linkexternal-'+client_id+'" value="" '+le_checked+' />'+M.str.repository.linkexternal+'</td></tr>';
596             }
598             if (!args.hasauthor) {
599                 // the author of the file
600                 html += '<tr><td class="mdl-right"><label for="text-author">'+M.str.repository.author+' :</label></td>';
601                 html += '<td class="mdl-left"><input id="text-author-'+client_id+'" type="text" name="author" value="'+this.options.author+'" /></td>';
602                 html += '</tr>';
603             }
605             if (!args.haslicense) {
606                 // the license of the file
607                 var licenses = this.options.licenses;
608                 html += '<tr><td class="mdl-right"><label for="select-license-'+client_id+'">'+M.str.repository.chooselicense+' :</label></td>';
609                 html += '<td class="mdl-left"><select name="license" id="select-license-'+client_id+'">';
610                 var recentlicense = YAHOO.util.Cookie.get('recentlicense');
611                 if (recentlicense) {
612                     this.options.defaultlicense=recentlicense;
613                 }
614                 for (var i in licenses) {
615                     if (this.options.defaultlicense==licenses[i].shortname) {
616                         var selected = ' selected';
617                     } else {
618                         var selected = '';
619                     }
620                     html += '<option value="'+licenses[i].shortname+'"'+selected+'>'+licenses[i].fullname+'</option>';
621                 }
622                 html += '</select></td></tr>';
623             }
624             html += '</table>';
626             html += '<p><input type="hidden" id="filesource-'+client_id+'" value="'+args.source+'" />';
627             html += '<input type="button" id="fp-confirm-'+client_id+'" value="'+M.str.repository.getfile+'" />';
628             html += '<input type="button" id="fp-cancel-'+client_id+'" value="'+M.str.moodle.cancel+'" /></p>';
629             html += '</div>';
631             var getfile_form = Y.Node.create(html);
632             panel.appendChild(getfile_form);
634             var getfile = Y.one('#fp-confirm-'+client_id);
635             getfile.on('click', function(e) {
636                 var client_id = this.options.client_id;
637                 var scope = this;
638                 var repository_id = this.active_repo.id;
639                 var title = Y.one('#newname-'+client_id).get('value');
640                 var filesource = Y.one('#filesource-'+client_id).get('value');
641                 var params = {'title':title, 'source':filesource, 'savepath': this.options.savepath};
642                 var license = Y.one('#select-license-'+client_id);
643                 if (license) {
644                     params['license'] = license.get('value');
645                     YAHOO.util.Cookie.set('recentlicense', license.get('value'));
646                 }
647                 var author = Y.one('#text-author-'+client_id);
648                 if (author){
649                     params['author'] = author.get('value');
650                 }
652                 if (this.options.env == 'editor') {
653                     // in editor, images are stored in '/' only
654                     params.savepath = '/';
655                     // when image or media button is clicked
656                     if ( this.options.return_types != 1 ) {
657                         var linkexternal = Y.one('#linkexternal-'+client_id).get('checked');
658                         if (linkexternal) {
659                             params['linkexternal'] = 'yes';
660                         }
661                     } else {
662                         // when link button in editor clicked
663                         params['linkexternal'] = 'yes';
664                     }
665                 }
667                 if (this.options.env == 'url') {
668                     params['linkexternal'] = 'yes';
669                 }
671                 this.wait('download', title);
672                 this.request({
673                     action:'download',
674                     client_id: client_id,
675                     repository_id: repository_id,
676                     'params': params,
677                     callback: function(id, obj, args) {
678                         if (scope.options.editor_target && scope.options.env=='editor') {
679                             scope.options.editor_target.value=obj.url;
680                             scope.options.editor_target.onchange();
681                         }
682                         scope.hide();
683                         obj.client_id = client_id;
684                         var formcallback_scope = null;
685                         if (args.scope.options.magicscope) {
686                             formcallback_scope = args.scope.options.magicscope;
687                         } else {
688                             formcallback_scope = args.scope;
689                         }
690                         scope.options.formcallback.apply(formcallback_scope, [obj]);
691                     }
692                 }, true);
693             }, this);
694             var elform = Y.one('#'+form_id);
695             elform.on('keydown', function(e) {
696                 if (e.keyCode == 13) {
697                     getfile.simulate('click');
698                     e.preventDefault();
699                 }
700             }, this);
701             var cancel = Y.one('#fp-cancel-'+client_id);
702             cancel.on('click', function(e) {
703                 this.view_files();
704             }, this);
705             var treeview = Y.one('#treeview-'+client_id);
706             if (treeview){
707                 treeview.setStyle('display', 'none');
708             }
709         },
710         wait: function(type) {
711             var panel = Y.one('#panel-'+this.options.client_id);
712             panel.set('innerHTML', '');
713             var name = '';
714             var str = '<div style="text-align:center">';
715             if(type=='load') {
716                 str += '<img src="'+M.util.image_url('i/loading')+'" />';
717                 str += '<p>'+M.str.repository.loading+'</p>';
718             }else{
719                 str += '<img src="'+M.util.image_url('i/progressbar')+'" />';
720                 str += '<p>'+M.str.repository.copying+' <strong>'+name+'</strong></p>';
721             }
722             str += '</div>';
723             try {
724                 panel.set('innerHTML', str);
725             } catch(e) {
726                 alert(e.toString());
727             }
728         },
729         render: function() {
730             var client_id = this.options.client_id;
731             var scope = this;
732             var filepicker_id = 'filepicker-'+client_id;
733             var fpnode = Y.Node.create('<div class="file-picker" id="'+filepicker_id+'"></div>');
734             Y.one(document.body).appendChild(fpnode);
735             // render file picker panel
736             this.mainui = new YAHOO.widget.Panel(filepicker_id, {
737                 draggable: true,
738                 close: true,
739                 underlay: 'none',
740                 zindex: 9999990,
741                 monitorresize: false,
742                 xy: [50, YAHOO.util.Dom.getDocumentScrollTop()+20]
743             });
744             var layout = null;
745             this.mainui.beforeRenderEvent.subscribe(function() {
746                 YAHOO.util.Event.onAvailable('layout-'+client_id, function() {
747                     layout = new YAHOO.widget.Layout('layout-'+client_id, {
748                         height: 480, width: 700,
749                         units: [
750                         {position: 'top', height: 32, resize: false,
751                         body:'<div class="yui-buttongroup fp-viewbar" id="fp-viewbar-'+client_id+'"></div><div class="fp-searchbar" id="search-div-'+client_id+'"></div>', gutter: '2'},
752                         {position: 'left', width: 200, resize: true, scroll:true,
753                         body:'<ul class="fp-list" id="fp-list-'+client_id+'"></ul>', gutter: '0 5 0 2', minWidth: 150, maxWidth: 300 },
754                         {position: 'center', body: '<div class="fp-panel" id="panel-'+client_id+'"></div>',
755                         scroll: true, gutter: '0 2 0 0' }
756                         ]
757                     });
758                     layout.render();
759                     scope.show_recent_repository();
760                 });
761             });
763             this.mainui.setHeader(M.str.repository.filepicker);
764             this.mainui.setBody('<div id="layout-'+client_id+'"></div>');
765             this.mainui.render();
766             this.rendered = true;
768             var scope = this;
769             // adding buttons
770             var view_icons = {label: M.str.repository.iconview, value: 't', 'checked': true,
771                 onclick: {
772                     fn: function(){
773                         scope.view_as_icons();
774                     }
775                 }
776             };
777             var view_listing = {label: M.str.repository.listview, value: 'l',
778                 onclick: {
779                     fn: function(){
780                         scope.view_as_list();
781                     }
782                 }
783             };
784             this.viewbar = new YAHOO.widget.ButtonGroup({
785                 id: 'btngroup-'+client_id,
786                 name: 'buttons',
787                 disabled: true,
788                 container: 'fp-viewbar-'+client_id
789             });
790             this.viewbar.addButtons([view_icons, view_listing]);
791             // processing repository listing
792             var r = this.options.repositories;
793             Y.on('contentready', function(el) {
794                 var list = Y.one(el);
795                 var count = 0;
796                 for (var i in r) {
797                     var id = 'repository-'+client_id+'-'+r[i].id;
798                     var link_id = id + '-link';
799                     list.append('<li id="'+id+'"><a class="fp-repo-name" id="'+link_id+'" href="###">'+r[i].name+'</a></li>');
800                     Y.one('#'+link_id).prepend('<img src="'+r[i].icon+'" width="16" height="16" />&nbsp;');
801                     Y.one('#'+link_id).on('click', function(e, scope, repository_id) {
802                         YAHOO.util.Cookie.set('recentrepository', repository_id);
803                         scope.repository_id = repository_id;
804                         this.list({'repo_id':repository_id});
805                     }, this /*handler running scope*/, this/*second argument*/, r[i].id/*third argument of handler*/);
806                     count++;
807                 }
808                 if (count==0) {
809                     if (this.options.externallink) {
810                         list.set('innerHTML', M.str.repository.norepositoriesexternalavailable);
811                     } else {
812                         list.set('innerHTML', M.str.repository.norepositoriesavailable);
813                     }
814                 }
815             }, '#fp-list-'+client_id, this /* handler running scope */, '#fp-list-'+client_id /*first argument of handler*/);
816         },
817         parse_repository_options: function(data) {
818             this.filelist = data.list?data.list:null;
819             this.filepath = data.path?data.path:null;
820             this.active_repo = {};
821             this.active_repo.issearchresult = Boolean(data.issearchresult);
822             this.active_repo.dynload = data.dynload?data.dynload:false;
823             this.active_repo.pages = Number(data.pages?data.pages:null);
824             this.active_repo.page = Number(data.page?data.page:null);
825             this.active_repo.id = data.repo_id?data.repo_id:null;
826             this.active_repo.nosearch = data.nosearch?true:false;
827             this.active_repo.norefresh = data.norefresh?true:false;
828             this.active_repo.nologin = data.nologin?true:false;
829             this.active_repo.logouttext = data.logouttext?data.logouttext:null;
830             this.active_repo.help = data.help?data.help:null;
831             this.active_repo.manage = data.manage?data.manage:null;
832         },
833         print_login: function(data) {
834             this.parse_repository_options(data);
835             var client_id = this.options.client_id;
836             var repository_id = data.repo_id;
837             var l = this.logindata = data.login;
838             var loginurl = '';
839             var panel = Y.one('#panel-'+client_id);
840             var action = 'login';
841             if (data['login_btn_action']) {
842                 action=data['login_btn_action'];
843             }
844             var form_id = 'fp-form-'+client_id;
845             var download_button_id = 'fp-form-download-button-'+client_id;
846             var search_button_id   = 'fp-form-search-button-'+client_id;
847             var login_button_id    = 'fp-form-login-button-'+client_id;
848             var popup_button_id    = 'fp-form-popup-button-'+client_id;
850             var str = '<div class="fp-login-form">';
851             str += '<form id="'+form_id+'">';
852             var has_pop = false;
853             str +='<table width="100%">';
854             for(var k in l) {
855                 str +='<tr>';
856                 if(l[k].type=='popup') {
857                     // pop element
858                     loginurl = l[k].url;
859                     str += '<td colspan="2"><p class="fp-popup">'+M.str.repository.popup+'</p>';
860                     str += '<p class="fp-popup"><button id="'+popup_button_id+'">'+M.str.repository.login+'</button>';
861                     str += '</p></td>';
862                     action = 'popup';
863                 }else if(l[k].type=='textarea') {
864                     // textarea element
865                     str += '<td colspan="2"><p><textarea id="'+l[k].id+'" name="'+l[k].name+'"></textarea></p></td>';
866                 }else if(l[k].type=='select') {
867                     // select element
868                     str += '<td align="right"><label>'+l[k].label+':</label></td>';
869                     str += '<td align="left"><select id="'+l[k].id+'" name="'+l[k].name+'">';
870                     for (i in l[k].options) {
871                         str += '<option value="'+l[k].options[i].value+'">'+l[k].options[i].label+'</option>';
872                     }
873                     str += '</select></td>';
874                 }else{
875                     // input element
876                     var label_id = '';
877                     var field_id = '';
878                     var field_value = '';
879                     if(l[k].id) {
880                         label_id = ' for="'+l[k].id+'"';
881                         field_id = ' id="'+l[k].id+'"';
882                     }
883                     if (l[k].label) {
884                         str += '<td align="right" width="30%" valign="center">';
885                         str += '<label'+label_id+'>'+l[k].label+'</label> </td>';
886                     } else {
887                         str += '<td width="30%"></td>';
888                     }
889                     if(l[k].value) {
890                         field_value = ' value="'+l[k].value+'"';
891                     }
892                     if(l[k].type=='radio'){
893                         var list = l[k].value.split('|');
894                         var labels = l[k].value_label.split('|');
895                         str += '<td align="left">';
896                         for(var item in list) {
897                             str +='<input type="'+l[k].type+'"'+' name="'+l[k].name+'"'+
898                                 field_id+' value="'+list[item]+'" />'+labels[item]+'<br />';
899                         }
900                         str += '</td>';
901                     }else{
902                         str += '<td align="left">';
903                         str += '<input type="'+l[k].type+'"'+' name="'+l[k].name+'"'+field_value+' '+field_id+' />';
904                         str += '</td>';
905                     }
906                 }
907                 str +='</tr>';
908             }
909             str +='</table>';
910             str += '</form>';
912             // custom lable text
913             var btn_label = data['login_btn_label']?data['login_btn_label']:M.str.repository.submit;
914             if (action != 'popup') {
915                 str += '<p><input type="button" id="';
916                 switch (action) {
917                     case 'search':
918                         str += search_button_id;
919                         break;
920                     case 'download':
921                         str += download_button_id;
922                         break;
923                     default:
924                         str += login_button_id;
925                         break;
926                 }
927                 str += '" value="'+btn_label+'" /></p>';
928             }
930             str += '</div>';
932             // insert login form
933             try {
934                 panel.set('innerHTML', str);
935             } catch(e) {
936                 alert(M.str.repository.xhtmlerror);
937             }
938             // register buttons
939             // process login action
940             var login_button = Y.one('#'+login_button_id);
941             var scope = this;
942             if (login_button) {
943                 login_button.on('click', function(){
944                     // collect form data
945                     var data = this.logindata;
946                     var scope = this;
947                     var params = {};
948                     for (var k in data) {
949                         if(data[k].type!='popup') {
950                             var el = Y.one('[name='+data[k].name+']');
951                             var type = el.get('type');
952                             params[data[k].name] = '';
953                             if(type == 'checkbox') {
954                                 params[data[k].name] = el.get('checked');
955                             } else {
956                                 params[data[k].name] = el.get('value');
957                             }
958                         }
959                     }
960                     // start ajax request
961                     this.request({
962                         'params': params,
963                         'scope': scope,
964                         'action':'signin',
965                         'path': '',
966                         'client_id': client_id,
967                         'repository_id': repository_id,
968                         'callback': function(id, o, args) {
969                             scope.parse_repository_options(o);
970                             scope.view_files();
971                         }
972                     }, true);
973                 }, this);
974             }
975             var search_button = Y.one('#'+search_button_id);
976             if (search_button) {
977                 search_button.on('click', function(){
978                     var data = this.logindata;
979                     var params = {};
981                     for (var k in data) {
982                         if(data[k].type!='popup') {
983                             var el = document.getElementsByName(data[k].name)[0];
984                             params[data[k].name] = '';
985                             if(el.type == 'checkbox') {
986                                 params[data[k].name] = el.checked;
987                             } else if(el.type == 'radio') {
988                                 var tmp = document.getElementsByName(data[k].name);
989                                 for(var i in tmp) {
990                                     if (tmp[i].checked) {
991                                         params[data[k].name] = tmp[i].value;
992                                     }
993                                 }
994                             } else {
995                                 params[data[k].name] = el.value;
996                             }
997                         }
998                     }
999                     this.request({
1000                             scope: scope,
1001                             action:'search',
1002                             client_id: client_id,
1003                             repository_id: repository_id,
1004                             form: {id: 'fp-form-'+scope.options.client_id,upload:false,useDisabled:true},
1005                             callback: function(id, o, args) {
1006                                 o.issearchresult = true;
1007                                 scope.parse_repository_options(o);
1008                                 scope.view_files();
1009                             }
1010                     }, true);
1011                 }, this);
1012             }
1013             var download_button = Y.one('#'+download_button_id);
1014             if (download_button) {
1015                 download_button.on('click', function(){
1016                     alert('download');
1017                 });
1018             }
1019             var popup_button = Y.one('#'+popup_button_id);
1020             if (popup_button) {
1021                 popup_button.on('click', function(e){
1022                     M.core_filepicker.active_filepicker = this;
1023                     window.open(loginurl, 'repo_auth', 'location=0,status=0,width=500,height=300,scrollbars=yes');
1024                     e.preventDefault();
1025                 }, this);
1026             }
1027             var elform = Y.one('#'+form_id);
1028             elform.on('keydown', function(e) {
1029                 if (e.keyCode == 13) {
1030                     switch (action) {
1031                         case 'search':
1032                             search_button.simulate('click');
1033                             break;
1034                         default:
1035                             login_button.simulate('click');
1036                             break;
1037                     }
1038                     e.preventDefault();
1039                 }
1040             }, this);
1042         },
1043         search: function(args) {
1044             var data = this.logindata;
1045             var params = {};
1047             for (var k in data) {
1048                 if(data[k].type!='popup') {
1049                     var el = document.getElementsByName(data[k].name)[0];
1050                     params[data[k].name] = '';
1051                     if(el.type == 'checkbox') {
1052                         params[data[k].name] = el.checked;
1053                     } else if(el.type == 'radio') {
1054                         var tmp = document.getElementsByName(data[k].name);
1055                         for(var i in tmp) {
1056                             if (tmp[i].checked) {
1057                                 params[data[k].name] = tmp[i].value;
1058                             }
1059                         }
1060                     } else {
1061                         params[data[k].name] = el.value;
1062                     }
1063                 }
1064             }
1065             this.request({
1066                     scope: scope,
1067                     action:'search',
1068                     client_id: client_id,
1069                     repository_id: repository_id,
1070                     form: {id: 'fp-form-'+scope.options.client_id,upload:false,useDisabled:true},
1071                     callback: function(id, o, args) {
1072                         o.issearchresult = true;
1073                         scope.parse_repository_options(o);
1074                         scope.view_files();
1075                     }
1076             }, true);
1077         },
1078         list: function(args) {
1079             var scope = this;
1080             if (!args) {
1081                 args = {};
1082             }
1083             if (!args.repo_id) {
1084                 args.repo_id = scope.active_repo.id;
1085             }
1086             scope.request({
1087                 action:'list',
1088                 client_id: scope.options.client_id,
1089                 repository_id: args.repo_id,
1090                 path:args.path?args.path:'',
1091                 page:args.page?args.page:'',
1092                 callback: function(id, obj, args) {
1093                     Y.all('#fp-list-'+scope.options.client_id+' li a').setStyle('backgroundColor', 'transparent');
1094                     var el = Y.one('#repository-'+scope.options.client_id+'-'+obj.repo_id+'-link');
1095                     if (el) {
1096                         el.setStyle('backgroundColor', '#AACCEE');
1097                     }
1098                     if (obj.login) {
1099                         scope.viewbar.set('disabled', true);
1100                         scope.print_login(obj);
1101                     } else if (obj.upload) {
1102                         scope.viewbar.set('disabled', true);
1103                         scope.parse_repository_options(obj);
1104                         scope.create_upload_form(obj);
1106                     } else if (obj.iframe) {
1108                     } else if (obj.list) {
1109                         obj.issearchresult = false;
1110                         scope.viewbar.set('disabled', false);
1111                         scope.parse_repository_options(obj);
1112                         scope.view_files();
1113                     }
1114                 }
1115             }, true);
1116         },
1117         create_upload_form: function(data) {
1118             var client_id = this.options.client_id;
1119             Y.one('#panel-'+client_id).set('innerHTML', '');
1120             var types = this.options.accepted_types;
1122             this.print_header();
1123             var id = data.upload.id+'_'+client_id;
1124             var str = '<div id="'+id+'_div" class="fp-upload-form mdl-align">';
1125             str += '<form id="'+id+'" enctype="multipart/form-data" method="POST">';
1126             str += '<table width="100%">';
1127             str += '<tr><td class="mdl-right">';
1128             str += '<label for="'+id+'_file">'+data.upload.label+': </label></td>';
1129             str += '<td class="mdl-left"><input type="file" id="'+id+'_file" name="repo_upload_file" />';
1130             str += '<tr><td class="mdl-right"><label for="newname-'+client_id+'">'+M.str.repository.saveas+':</label></td>';
1131             str += '<td class="mdl-left"><input type="text" name="title" id="newname-'+client_id+'" value="" /></td></tr>';
1132             str += '<input type="hidden" name="itemid" value="'+this.options.itemid+'" />';
1133             for (var i in types) {
1134                 str += '<input type="hidden" name="accepted_types[]" value="'+types[i]+'" />';
1135             }
1136             str += '</td></tr><tr>';
1137             str += '<td class="mdl-right"><label>'+M.str.repository.author+': </label></td>';
1138             str += '<td class="mdl-left"><input type="text" name="author" value="'+this.options.author+'" /></td>';
1139             str += '</tr>';
1140             str += '<tr>';
1141             str += '<td class="mdl-right">'+M.str.repository.chooselicense+': </td>';
1142             str += '<td class="mdl-left">';
1143             var licenses = this.options.licenses;
1144             str += '<select name="license" id="select-license-'+client_id+'">';
1145             var recentlicense = YAHOO.util.Cookie.get('recentlicense');
1146             if (recentlicense) {
1147                 this.options.defaultlicense=recentlicense;
1148             }
1149             for (var i in licenses) {
1150                 if (this.options.defaultlicense==licenses[i].shortname) {
1151                     var selected = ' selected';
1152                 } else {
1153                     var selected = '';
1154                 }
1155                 str += '<option value="'+licenses[i].shortname+'"'+selected+'>'+licenses[i].fullname+'</option>';
1156             }
1157             str += '</select>';
1158             str += '</td>';
1159             str += '</tr></table>';
1160             str += '</form>';
1161             str += '<div class="fp-upload-btn"><button id="'+id+'_action">'+M.str.repository.upload+'</button></div>';
1162             str += '</div>';
1163             var upload_form = Y.Node.create(str);
1164             Y.one('#panel-'+client_id).appendChild(upload_form);
1165             var scope = this;
1166             Y.one('#'+id+'_action').on('click', function(e) {
1167                 e.preventDefault();
1168                 var license = Y.one('#select-license-'+client_id).get('value');
1169                 YAHOO.util.Cookie.set('recentlicense', license);
1170                 if (!Y.one('#'+id+'_file').get('value')) {
1171                     scope.print_msg(M.str.repository.nofilesattached, 'error');
1172                     return false;
1173                 }
1174                 Y.use('io-upload-iframe', function() {
1175                     scope.request({
1176                             scope: scope,
1177                             action:'upload',
1178                             client_id: client_id,
1179                             params: {'savepath':scope.options.savepath},
1180                             repository_id: scope.active_repo.id,
1181                             form: {id: id, upload:true},
1182                             callback: function(id, o, args) {
1183                                 if (scope.options.editor_target&&scope.options.env=='editor') {
1184                                     scope.options.editor_target.value=o.url;
1185                                     scope.options.editor_target.onchange();
1186                                 }
1187                                 scope.hide();
1188                                 o.client_id = client_id;
1189                                 var formcallback_scope = null;
1190                                 if (args.scope.options.magicscope) {
1191                                     formcallback_scope = args.scope.options.magicscope;
1192                                 } else {
1193                                     formcallback_scope = args.scope;
1194                                 }
1195                                 scope.options.formcallback.apply(formcallback_scope, [o]);
1196                             }
1197                     }, true);
1198                 });
1199             }, this);
1200         },
1201         print_header: function() {
1202             var r = this.active_repo;
1203             var scope = this;
1204             var client_id = this.options.client_id;
1205             var repository_id = this.active_repo.id;
1206             var panel = Y.one('#panel-'+client_id);
1207             var str = '<div id="fp-header-'+client_id+'">';
1208             str += '<div class="fp-toolbar" id="repo-tb-'+client_id+'"></div>';
1209             str += '</div>';
1210             var head = Y.Node.create(str);
1211             panel.appendChild(head);
1212             //if(this.active_repo.pages < 8){
1213                 this.print_paging('header');
1214             //}
1216             var toolbar = Y.one('#repo-tb-'+client_id);
1218             if(!r.nosearch) {
1219                 var html = '<a href="###"><img src="'+M.util.image_url('a/search')+'" /> '+M.str.repository.search+'</a>';
1220                 var search = Y.Node.create(html);
1221                 search.on('click', function() {
1222                     scope.request({
1223                         scope: scope,
1224                         action:'searchform',
1225                         repository_id: repository_id,
1226                         callback: function(id, obj, args) {
1227                             var scope = args.scope;
1228                             var client_id = scope.options.client_id;
1229                             var repository_id = scope.active_repo.id;
1230                             var container = document.getElementById('fp-search-dlg');
1231                             if(container) {
1232                                 container.innerHTML = '';
1233                                 container.parentNode.removeChild(container);
1234                             }
1235                             var container = document.createElement('DIV');
1236                             container.id = 'fp-search-dlg';
1238                             var dlg_title = document.createElement('DIV');
1239                             dlg_title.className = 'hd';
1240                             dlg_title.innerHTML = M.str.repository.search;
1242                             var dlg_body = document.createElement('DIV');
1243                             dlg_body.className = 'bd';
1245                             var sform = document.createElement('FORM');
1246                             sform.method = 'POST';
1247                             sform.id = "fp-search-form";
1248                             sform.innerHTML = obj.form;
1250                             dlg_body.appendChild(sform);
1251                             container.appendChild(dlg_title);
1252                             container.appendChild(dlg_body);
1253                             Y.one(document.body).appendChild(container);
1254                             var search_dialog= null;
1255                             function dialog_handler() {
1256                                 scope.viewbar.set('disabled', false);
1257                                 scope.request({
1258                                         scope: scope,
1259                                         action:'search',
1260                                         client_id: client_id,
1261                                         repository_id: repository_id,
1262                                         form: {id: 'fp-search-form',upload:false,useDisabled:true},
1263                                         callback: function(id, o, args) {
1264                                             scope.parse_repository_options(o);
1265                                             scope.view_files();
1266                                         }
1267                                 }, true);
1268                                 search_dialog.cancel();
1269                             }
1270                             Y.one('#fp-search-form').on('keydown', function(e){
1271                                 if (e.keyCode == 13) {
1272                                     dialog_handler();
1273                                     e.preventDefault();
1274                                 }
1275                             }, this);
1277                             search_dialog = new YAHOO.widget.Dialog("fp-search-dlg", {
1278                                postmethod: 'async',
1279                                draggable: true,
1280                                width : "30em",
1281                                modal: true,
1282                                fixedcenter : true,
1283                                zindex: 9999991,
1284                                visible : false,
1285                                constraintoviewport : true,
1286                                buttons: [
1287                                {
1288                                    text:M.str.repository.submit,
1289                                    handler:dialog_handler,
1290                                    isDefault:true
1291                                }, {
1292                                    text:M.str.moodle.cancel,
1293                                    handler:function(){
1294                                        this.destroy()
1295                                    }
1296                                }]
1297                             });
1298                             search_dialog.render();
1299                             search_dialog.show();
1300                         }
1301                     });
1302                 },this);
1303                 toolbar.appendChild(search);
1304             }
1305             // weather we use cache for this instance, this button will reload listing anyway
1306             if(!r.norefresh) {
1307                 var html = '<a href="###"><img src="'+M.util.image_url('a/refresh')+'" /> '+M.str.repository.refresh+'</a>';
1308                 var refresh = Y.Node.create(html);
1309                 refresh.on('click', function() {
1310                     this.list();
1311                 }, this);
1312                 toolbar.appendChild(refresh);
1313             }
1314             if(!r.nologin) {
1315                 var label = r.logouttext?r.logouttext:M.str.repository.logout;
1316                 var html = '<a href="###"><img src="'+M.util.image_url('a/logout')+'" /> '+label+'</a>';
1317                 var logout = Y.Node.create(html);
1318                 logout.on('click', function() {
1319                     this.request({
1320                         action:'logout',
1321                         client_id: client_id,
1322                         repository_id: repository_id,
1323                         path:'',
1324                         callback: function(id, obj, args) {
1325                             scope.viewbar.set('disabled', true);
1326                             scope.print_login(obj);
1327                         }
1328                     }, true);
1329                 }, this);
1330                 toolbar.appendChild(logout);
1331             }
1333             if(r.manage) {
1334                 var mgr = document.createElement('A');
1335                 mgr.href = r.manage;
1336                 mgr.target = "_blank";
1337                 mgr.innerHTML = '<img src="'+M.util.image_url('a/setting')+'" /> '+M.str.repository.manageurl;
1338                 toolbar.appendChild(mgr);
1339             }
1340             if(r.help) {
1341                 var help = document.createElement('A');
1342                 help.href = r.help;
1343                 help.target = "_blank";
1344                 help.innerHTML = '<img src="'+M.util.image_url('a/help')+'" /> '+M.str.repository.help;
1345                 toolbar.appendChild(help);
1346             }
1348             this.print_path();
1349         },
1350         get_page_button: function(page) {
1351             var r = this.active_repo;
1352             var css = '';
1353             if (page == r.page) {
1354                 css = 'class="cur_page" ';
1355             }
1356             var str = '<a '+css+'href="###" id="repo-page-'+page+'">';
1357             return str;
1358         },
1359         print_paging: function(html_id) {
1360             var client_id = this.options.client_id;
1361             var scope = this;
1362             var r = this.active_repo;
1363             var str = '';
1364             var action = '';
1365             if(r.pages > 1) {
1366                 str += '<div class="fp-paging" id="paging-'+html_id+'-'+client_id+'">';
1367                 str += this.get_page_button(1)+'1</a> ';
1369                 var span = 5;
1370                 var ex = (span-1)/2;
1372                 if (r.page+ex>=r.pages) {
1373                     var max = r.pages;
1374                 } else {
1375                     if (r.page<span) {
1376                         var max = span;
1377                     } else {
1378                         var max = r.page+ex;
1379                     }
1380                 }
1382                 // won't display upper boundary
1383                 if (r.page >= span) {
1384                     str += ' ... ';
1385                     for(var i=r.page-ex; i<max; i++) {
1386                         str += this.get_page_button(i);
1387                         str += String(i);
1388                         str += '</a> ';
1389                     }
1390                 } else {
1391                     // this very first elements
1392                     for(var i = 2; i < max; i++) {
1393                         str += this.get_page_button(i);
1394                         str += String(i);
1395                         str += '</a> ';
1396                     }
1397                 }
1399                 // won't display upper boundary
1400                 if (max==r.pages) {
1401                     str += this.get_page_button(r.pages)+r.pages+'</a>';
1402                 } else {
1403                     str += this.get_page_button(max)+max+'</a>';
1404                     str += ' ... '+this.get_page_button(r.pages)+r.pages+'</a>';
1405                 }
1406                 str += '</div>';
1407             }
1408             if (str) {
1409                 var a = Y.Node.create(str);
1410                 Y.one('#fp-header-'+client_id).appendChild(a);
1412                 Y.all('#fp-header-'+client_id+' .fp-paging a').each(
1413                     function(node, id) {
1414                         node.on('click', function(e) {
1415                             var id = node.get('id');
1416                             var re = new RegExp("repo-page-(\\d+)", "i");
1417                             var result = id.match(re);
1418                             var args = {};
1419                             args.page = result[1];
1420                             if (scope.active_repo.issearchresult) {
1421                                 scope.request({
1422                                         scope: scope,
1423                                         action:'search',
1424                                         client_id: client_id,
1425                                         repository_id: r.id,
1426                                         params: {'page':result[1]},
1427                                         callback: function(id, o, args) {
1428                                             o.issearchresult = true;
1429                                             scope.parse_repository_options(o);
1430                                             scope.view_files(result[1]);
1431                                         }
1432                                 }, true);
1434                             } else {
1435                                 if (scope.viewmode == 2) {
1436                                     scope.view_as_list(result[1]);
1437                                 } else {
1438                                     scope.list(args);
1439                                 }
1440                             }
1441                         });
1442                     });
1443             }
1444         },
1445         print_path: function() {
1446             var client_id = this.options.client_id;
1447             var panel = Y.one('#panel-'+client_id);
1448             var p = this.filepath;
1449             if (p && p.length!=0) {
1450                 var path = Y.Node.create('<div id="path-'+client_id+'" class="fp-pathbar"></div>');
1451                 panel.appendChild(path);
1452                 for(var i = 0; i < p.length; i++) {
1453                     var link_path = p[i].path;
1454                     var link = document.createElement('A');
1455                     link.href = "###";
1456                     link.innerHTML = p[i].name;
1457                     link.id = 'path-node-'+client_id+'-'+i;
1458                     var sep = Y.Node.create('<span>/</span>');
1459                     path.appendChild(link);
1460                     path.appendChild(sep);
1461                     Y.one('#'+link.id).on('click', function(Y, path){
1462                         this.list({'path':path});
1463                         }, this, link_path)
1464                 }
1465             }
1466         },
1467         hide: function() {
1468             this.mainui.hide();
1469         },
1470         show: function() {
1471             if (this.rendered) {
1472                 var panel = Y.one('#panel-'+this.options.client_id);
1473                 panel.set('innerHTML', '');
1474                 this.mainui.show();
1475                 this.show_recent_repository();
1476             } else {
1477                 this.launch();
1478             }
1479         },
1480         launch: function() {
1481             this.render();
1482         },
1483         show_recent_repository: function() {
1484             var repository_id = YAHOO.util.Cookie.get('recentrepository');
1485             if (this.options.repositories[repository_id]) {
1486                 this.list({'repo_id':repository_id});
1487             }
1488         }
1489     });
1490     var loading = Y.one('#filepicker-loading-'+options.client_id);
1491     if (loading) {
1492         loading.setStyle('display', 'none');
1493     }
1494     M.core_filepicker.instances[options.client_id] = new FilePickerHelper(options);