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