mirror of
https://github.com/moodle/moodle.git
synced 2025-01-17 21:49:15 +01:00
MDL-31901: Allow FileManager to re-use FilePicker JS code for view modes:
- when loading core_filepicker we extend the Node element with functions necessary to display files list in different view modes; - repository/filepicker.js is changed to use those functions; - FileManager now has three different view modes (icon view, tree view and table view), JS code is re-used from FilePicker; - files in FileManager no longer have context menu, they have one popup Widget with different actions instead; - Added more templates for JS code to FileManager, use similar CSS class names as FilePicker; - lib/filelib.php : fixed double slashes in path, return more data about files; - lib/form/filemanager.php : pass information to FileManager about available licenses and default author; - repository/draftfiles_ajax.php : return information about directory tree for file moving UI in FileManager, return formatted information; - repository/lib.php : function repository::prepare_listing() now can work also with draftarea files listing;
This commit is contained in:
parent
d1d186917c
commit
e709ddd29c
@ -116,9 +116,7 @@ class core_files_renderer extends plugin_renderer_base {
|
||||
if (empty($filemanagertemplateloaded)) {
|
||||
$filemanagertemplateloaded = true;
|
||||
$this->page->requires->js_init_call('M.form_filemanager.set_templates',
|
||||
array(array(
|
||||
'onefile' => '___fullname___ ___action___'
|
||||
)), true, $module);
|
||||
array($this->filemanager_js_templates()), true, $module);
|
||||
}
|
||||
$this->page->requires->js_init_call('M.form_filemanager.init', array($fm->options), true, $module);
|
||||
|
||||
@ -156,11 +154,21 @@ class core_files_renderer extends plugin_renderer_base {
|
||||
* If browser supports Drag-and-drop, the body element will have class 'dndsupported',
|
||||
* otherwise - 'dndnotsupported';
|
||||
*
|
||||
* Element with class 'fm-filelist' will be populated with files list;
|
||||
* Element with class 'fm-breadcrumb' will be populated with the path or have class 'fm-empty' when empty;
|
||||
* Element with class 'fm-btn-add' will hold onclick event for adding a file (opening filepicker);
|
||||
* Element with class 'fm-btn-mkdir' will hold onclick event for adding new folder;
|
||||
* Element with class 'fm-btn-download' will hold onclick event for download action;
|
||||
* Element with class 'fp-content' will be populated with files list;
|
||||
* Element with class 'fp-btn-add' will hold onclick event for adding a file (opening filepicker);
|
||||
* Element with class 'fp-btn-mkdir' will hold onclick event for adding new folder;
|
||||
* Element with class 'fp-btn-download' will hold onclick event for download action;
|
||||
*
|
||||
* Element with class 'fp-path-folder' is a template for one folder in path toolbar.
|
||||
* It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
|
||||
* Parent element will receive class 'empty' when there are no folders to be displayed;
|
||||
* The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
|
||||
*
|
||||
* Element with class 'fp-viewbar' will have the class 'enabled' or 'disabled' when view mode
|
||||
* can be changed or not;
|
||||
* Inside element with class 'fp-viewbar' there are expected elements with classes
|
||||
* 'fp-vb-icons', 'fp-vb-tree' and 'fp-vb-details'. They will handle onclick events to switch
|
||||
* between the view modes, the last clicked element will have the class 'checked';
|
||||
*
|
||||
* @param form_filemanager $fm
|
||||
* @return string
|
||||
@ -181,30 +189,144 @@ class core_files_renderer extends plugin_renderer_base {
|
||||
$strdndenabledinbox = get_string('dndenabled_inbox', 'moodle');
|
||||
$loading = get_string('loading', 'repository');
|
||||
|
||||
$html .= <<<FMHTML
|
||||
<div id="filemanager-{$client_id}" class="filemanager fm-loading">
|
||||
<div class="filemanager-loading mdl-align">{$icon_progress}</div>
|
||||
<div class="fm-breadcrumb"></div>
|
||||
$html = '
|
||||
<div id="filemanager-'.$client_id.'" class="filemanager fm-loading">
|
||||
<div class="filemanager-loading mdl-align">'.$icon_progress.'</div>
|
||||
<div class="fp-pathbar">
|
||||
<span class="{!}fp-path-folder"><a class="{!}fp-path-folder-name"></a><span>/</span></span>
|
||||
</div>
|
||||
<div class="filemanager-toolbar">
|
||||
<input type="button" class="fm-btn-add" value="{$straddfile}" />
|
||||
<input type="button" class="fm-btn-mkdir" value="{$strmakedir}" />
|
||||
<input type="button" class="fm-btn-download" value="{$strdownload}" />
|
||||
{$restrictions}
|
||||
<span class="dndupload-message"> - $strdndenabled </span>
|
||||
<input type="button" class="{!}fp-btn-add" value="'.$straddfile.'" />
|
||||
<input type="button" class="{!}fp-btn-mkdir" value="'.$strmakedir.'" />
|
||||
<input type="button" class="{!}fp-btn-download" value="'.$strdownload.'" />
|
||||
'.$restrictions.'
|
||||
<span class="dndupload-message"> - '.$strdndenabled.' </span>
|
||||
<div class="{!}fp-viewbar" style="float:none;">
|
||||
<span class=""><button class="{!}fp-vb-icons">'.get_string('iconview', 'repository').'</button></span>
|
||||
<span class=""><button class="{!}fp-vb-tree">'.get_string('listview', 'repository').'</button></span>
|
||||
<span class=""><button class="{!}fp-vb-details">'.get_string('detailview', 'repository').'</button></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filemanager-container" >
|
||||
<ul class="fm-filelist"></ul>
|
||||
<div class="fm-empty-container mdl-align">{$strnofilesattached}
|
||||
<span class="dndupload-message">{$strdndenabledinbox}</span>
|
||||
<div class="fm-content-wrapper">
|
||||
<ul class="fp-content"></ul>
|
||||
<div class="fm-empty-container mdl-align">'.$strnofilesattached.'
|
||||
<span class="dndupload-message">'.$strdndenabledinbox.'</span>
|
||||
</div>
|
||||
<div class="dndupload-target">'.$strdroptoupload.'</div>
|
||||
<div class="dndupload-uploadinprogress">'.$icon_progress.'</div>
|
||||
</div>
|
||||
<div class="dndupload-target">{$strdroptoupload}</div>
|
||||
<div class="dndupload-uploadinprogress">{$icon_progress}</div>
|
||||
<div class="filemanager-updating">{$icon_progress}</div>
|
||||
<div class="filemanager-updating">'.$icon_progress.'</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="clearer"></div>
|
||||
FMHTML;
|
||||
return $html;
|
||||
';
|
||||
return preg_replace('/\{\!\}/', '', $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* FileManager JS template for displaying one file in 'icon view' mode.
|
||||
*
|
||||
* @see fp_js_template_iconfilename()
|
||||
* @return string
|
||||
*/
|
||||
private function fm_js_template_iconfilename() {
|
||||
return $this->fp_js_template_iconfilename();
|
||||
}
|
||||
|
||||
/**
|
||||
* FileManager JS template for displaying file name in 'table view' and 'tree view' modes.
|
||||
*
|
||||
* @see fp_js_template_listfilename()
|
||||
* @return string
|
||||
*/
|
||||
private function fm_js_template_listfilename() {
|
||||
return $this->fp_js_template_listfilename();
|
||||
}
|
||||
|
||||
/**
|
||||
* FileManager JS template for window with file information/actions.
|
||||
*
|
||||
* All content must be enclosed in an element with class 'fp-select', CSS for this class
|
||||
* must define width and height of the window;
|
||||
*
|
||||
* Thumbnail image will be added as content to the element with class 'fp-thumbnail';
|
||||
*
|
||||
* Inside the window the elements with the following classnames must be present:
|
||||
* 'fp-saveas', 'fp-author', 'fp-license', 'fp-path'. Inside each of them must be
|
||||
* one input element (or select in case of fp-license and fp-path). They may also have labels.
|
||||
* The elements will be assign with class 'uneditable' and input/select element will become
|
||||
* disabled if they are not applicable for the particular file;
|
||||
*
|
||||
* There may be present elements with classes 'fp-origpath', 'fp-datemodified', 'fp-datecreated',
|
||||
* 'fp-size', 'fp-dimensions'. They will receive additional class 'fp-unknown' if information
|
||||
* is unavailable. If there is information available, the content of embedded element
|
||||
* with class 'fp-value' will be substituted with the value;
|
||||
*
|
||||
* Elements with classes 'fp-file-update', 'fp-file-download', 'fp-file-delete', 'fp-file-zip',
|
||||
* 'fp-file-unzip', 'fp-file-setmain' and 'fp-file-cancel' will hold corresponding onclick
|
||||
* events (there may be several elements with class 'fp-file-cancel');
|
||||
*
|
||||
* When confirm button is pressed and file is being selected, the top element receives
|
||||
* additional class 'loading'. It is removed when response from server is received.
|
||||
*
|
||||
* When any of the input fields is changed, the top element receives class 'fp-changed';
|
||||
* When current file can be set as main - top element receives class 'fp-cansetmain';
|
||||
* When current file is folder/zip/file - top element receives respectfully class
|
||||
* 'fp-folder'/'fp-zip'/'fp-file';
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function fm_js_template_fileselectlayout() {
|
||||
$rv = '<div class="{!}fp-select">
|
||||
<div class="fp-select-loading">
|
||||
<img src="'.$this->pix_url('i/loading').'" />
|
||||
<p>'.get_string('loading', 'repository').'</p>
|
||||
</div>
|
||||
<form>
|
||||
<p class="{!}fp-thumbnail"></p>
|
||||
<table width="100%">
|
||||
<tr class="{!}fp-saveas"><td class="mdl-right"><label>'.get_string('name', 'moodle').'</label>:</td>
|
||||
<td class="mdl-left"><input type="text"/></td></tr>
|
||||
<tr class="{!}fp-author"><td class="mdl-right"><label>'.get_string('author', 'repository').'</label>:</td>
|
||||
<td class="mdl-left"><input type="text" /></td></tr>
|
||||
<tr class="{!}fp-license"><td class="mdl-right"><label>'.get_string('chooselicense', 'repository').'</label>:</td>
|
||||
<td class="mdl-left"><select></select></td></tr>
|
||||
<tr class="{!}fp-path"><td class="mdl-right"><label>'.get_string('path', 'moodle').'</label>:</td>
|
||||
<td class="mdl-left"><select></select></td></tr>
|
||||
<tr class="{!}fp-origpath"><td class="mdl-right"><label>'.get_string('originalpath', 'moodle').'</label>:</td>
|
||||
<td class="mdl-left"><span class="fp-value"/></td></tr>
|
||||
</table>
|
||||
<p><button class="{!}fp-file-update" >'.get_string('update', 'moodle').'</button>
|
||||
<button class="{!}fp-file-download" >'.get_string('download').'</button>
|
||||
<button class="{!}fp-file-delete" >'.get_string('delete').'</button>
|
||||
<button class="{!}fp-file-zip" >'.get_string('zip', 'editor').'</button>
|
||||
<button class="{!}fp-file-unzip" >'.get_string('unzip').'</button>
|
||||
<button class="{!}fp-file-setmain" >'.get_string('setmainfile', 'repository').'</button>
|
||||
<button class="{!}fp-file-cancel" >'.get_string('cancel').'</button>
|
||||
</p>
|
||||
</form>
|
||||
<div class="{!}fp-datemodified">'.get_string('lastmodified', 'moodle').': <span class="fp-value"/></div>
|
||||
<div class="{!}fp-datecreated">'.get_string('datecreated', 'repository').': <span class="fp-value"/></div>
|
||||
<div class="{!}fp-size">'.get_string('size', 'repository').': <span class="fp-value"/></div>
|
||||
<div class="{!}fp-dimensions">'.get_string('dimensions', 'repository').': <span class="fp-value"/></div>
|
||||
</div>';
|
||||
return preg_replace('/\{\!\}/', '', $rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all FileManager JavaScript templates as an array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function filemanager_js_templates() {
|
||||
$class_methods = get_class_methods($this);
|
||||
$templates = array();
|
||||
foreach ($class_methods as $method_name) {
|
||||
if (preg_match('/^fm_js_template_(.*)$/', $method_name, $matches))
|
||||
$templates[$matches[1]] = $this->$method_name();
|
||||
}
|
||||
return $templates;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,10 +373,10 @@ FMHTML;
|
||||
*
|
||||
* Element with class 'fp-paging' will contain page navigation (will be deprecated soon);
|
||||
*
|
||||
* Element with class 'fp-path-folder' will contain template for one folder in path toolbar.
|
||||
* Element with class 'fp-path-folder' is a template for one folder in path toolbar.
|
||||
* It will hold mouse click event and will be assigned classes first/last/even/odd respectfully.
|
||||
* The content of element with class 'fp-path-folder-name' will be substituted with folder name;
|
||||
* Parent element will receive class 'empty' when there are no folders to be displayed;
|
||||
* The content of subelement with class 'fp-path-folder-name' will be substituted with folder name;
|
||||
*
|
||||
* Element with class 'fp-toolbar' will have class 'empty' if all 'Back', 'Search', 'Refresh',
|
||||
* 'Logout', 'Manage' and 'Help' are unavailable for this repo;
|
||||
@ -310,10 +432,7 @@ FMHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* FilePicker JS template for displaying list of files in 'icon view' mode.
|
||||
*
|
||||
* Element with class 'fp-file' is a template for displaying one file and indicates a place
|
||||
* where files shall be output. It also will hold mouse events (click, over, out, etc.);
|
||||
* FilePicker JS template for displaying one file in 'icon view' mode.
|
||||
*
|
||||
* the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
|
||||
* (both width and height, unless min-width and/or min-height is set in CSS) and the content of
|
||||
@ -323,15 +442,17 @@ FMHTML;
|
||||
* (unless min-width is set in css) and the content of an element will be replaced with filename
|
||||
* supplied by repository;
|
||||
*
|
||||
* top element(s) will have class fp-folder if the element is a folder;
|
||||
*
|
||||
* List of files will have parent <div> element with class 'fp-iconview'
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function fp_js_template_iconview() {
|
||||
$rv = '<div class="fp-iconview">
|
||||
<div class="{!}fp-file">
|
||||
private function fp_js_template_iconfilename() {
|
||||
$rv = '<div class="fp-file">
|
||||
<div class="{!}fp-thumbnail"></div>
|
||||
<div class="{!}fp-filename"></div>
|
||||
</div>
|
||||
</div>';
|
||||
</div>';
|
||||
return preg_replace('/\{\!\}/', '', $rv);
|
||||
}
|
||||
|
||||
@ -343,6 +464,8 @@ FMHTML;
|
||||
* content of element with class 'fp-filename' will be replaced with filename supplied by
|
||||
* repository;
|
||||
*
|
||||
* top element(s) will have class fp-folder if the element is a folder;
|
||||
*
|
||||
* Note that tree view and table view are the YUI widgets and therefore there are no
|
||||
* other templates. The widgets will be wrapped in <div> with class fp-treeview or
|
||||
* fp-tableview (respectfully).
|
||||
@ -350,7 +473,7 @@ FMHTML;
|
||||
* @return string
|
||||
*/
|
||||
private function fp_js_template_listfilename() {
|
||||
$rv = '<span class="{!}fp-icon"></span> <span class="{!}fp-filename"></span>';
|
||||
$rv = '<span><span class="{!}fp-icon"></span> <span class="{!}fp-filename"></span></span>';
|
||||
return preg_replace('/\{\!\}/', '', $rv);
|
||||
}
|
||||
|
||||
@ -379,7 +502,7 @@ FMHTML;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template for window appearing to select a file.
|
||||
* FilePicker JS template for window appearing to select a file.
|
||||
*
|
||||
* All content must be enclosed in an element with class 'fp-select', CSS for this class
|
||||
* must define width and height of the window;
|
||||
@ -393,9 +516,9 @@ FMHTML;
|
||||
* disabled if they are not applicable for the particular file;
|
||||
*
|
||||
* There may be present elements with classes 'fp-datemodified', 'fp-datecreated', 'fp-size',
|
||||
* 'fp-license', 'fp-author'. They will receive additional class 'fp-unknown' if information
|
||||
* is unavailable. If there is information available, the content of embedded element
|
||||
* with class 'fp-value' will be substituted with the value;
|
||||
* 'fp-license', 'fp-author', 'fp-dimensions'. They will receive additional class 'fp-unknown'
|
||||
* if information is unavailable. If there is information available, the content of embedded
|
||||
* element with class 'fp-value' will be substituted with the value;
|
||||
*
|
||||
* Elements with classes 'fp-select-confirm' and 'fp-select-cancel' will hold corresponding
|
||||
* onclick events;
|
||||
|
@ -1242,6 +1242,7 @@ $string['olduserdirectory'] = 'This is the OLD users directory, and is no longer
|
||||
$string['opentoguests'] = 'Guest access';
|
||||
$string['optional'] = 'optional';
|
||||
$string['order'] = 'Order';
|
||||
$string['originalpath'] = 'Original path';
|
||||
$string['orphanedactivities'] = 'Orphaned activities';
|
||||
$string['other'] = 'Other';
|
||||
$string['outline'] = 'Outline';
|
||||
|
@ -566,13 +566,13 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') {
|
||||
$data->path[] = array('name'=>get_string('files'), 'path'=>'/');
|
||||
|
||||
// will be used to build breadcrumb
|
||||
$trail = '';
|
||||
$trail = '/';
|
||||
if ($filepath !== '/') {
|
||||
$filepath = file_correct_filepath($filepath);
|
||||
$parts = explode('/', $filepath);
|
||||
foreach ($parts as $part) {
|
||||
if ($part != '' && $part != null) {
|
||||
$trail .= ('/'.$part.'/');
|
||||
$trail .= ($part.'/');
|
||||
$data->path[] = array('name'=>$part, 'path'=>$trail);
|
||||
}
|
||||
}
|
||||
@ -587,11 +587,16 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') {
|
||||
$item->filepath = $file->get_filepath();
|
||||
$item->fullname = trim($item->filename, '/');
|
||||
$filesize = $file->get_filesize();
|
||||
$item->size = $filesize ? $filesize : null;
|
||||
$item->filesize = $filesize ? display_size($filesize) : '';
|
||||
|
||||
$icon = mimeinfo_from_type('icon', $file->get_mimetype());
|
||||
$item->icon = $OUTPUT->pix_url('f/' . $icon)->out();
|
||||
$item->sortorder = $file->get_sortorder();
|
||||
$item->author = $file->get_author();
|
||||
$item->license = $file->get_license();
|
||||
$item->datemodified = $file->get_timemodified();
|
||||
$item->datecreated = $file->get_timecreated();
|
||||
|
||||
if ($icon == 'zip') {
|
||||
$item->type = 'zip';
|
||||
@ -605,9 +610,11 @@ function file_get_drafarea_files($draftitemid, $filepath = '/') {
|
||||
$item->type = 'folder';
|
||||
$foldername = explode('/', trim($item->filepath, '/'));
|
||||
$item->fullname = trim(array_pop($foldername), '/');
|
||||
$item->thumbnail = $OUTPUT->pix_url('f/folder-32')->out(false);
|
||||
} else {
|
||||
// do NOT use file browser here!
|
||||
$item->url = moodle_url::make_draftfile_url($draftitemid, $item->filepath, $item->filename)->out();
|
||||
$item->thumbnail = $OUTPUT->pix_url(file_extension_icon($item->filename, 32))->out(false);
|
||||
}
|
||||
$list[] = $item;
|
||||
}
|
||||
|
@ -80,6 +80,7 @@ M.form_filemanager.init = function(Y, options) {
|
||||
} else {
|
||||
this.filecount = 0;
|
||||
}
|
||||
// prepare filemanager for drag-and-drop upload
|
||||
this.filemanager = Y.one('#filemanager-'+options.client_id);
|
||||
if (this.filemanager.hasClass('filemanager-container') || !this.filemanager.one('.filemanager-container')) {
|
||||
this.dndcontainer = this.filemanager;
|
||||
@ -89,7 +90,31 @@ M.form_filemanager.init = function(Y, options) {
|
||||
this.dndcontainer.generateID();
|
||||
}
|
||||
}
|
||||
// save template for one path element and location of path bar
|
||||
if (this.filemanager.one('.fp-path-folder')) {
|
||||
this.pathnode = this.filemanager.one('.fp-path-folder');
|
||||
this.pathbar = this.pathnode.get('parentNode');
|
||||
this.pathbar.removeChild(this.pathnode);
|
||||
}
|
||||
// initialize 'select file' panel
|
||||
var fpselectnode = Y.Node.create(M.form_filemanager.templates.fileselectlayout);
|
||||
this.filemanager.appendChild(fpselectnode);
|
||||
this.selectui = new Y.Panel({
|
||||
srcNode : fpselectnode,
|
||||
zIndex : 600000,
|
||||
centered : true,
|
||||
modal : true,
|
||||
close : true,
|
||||
render : true
|
||||
});
|
||||
this.selectui.hide();
|
||||
this.setup_select_file();
|
||||
// setup buttons onclick events
|
||||
this.setup_buttons();
|
||||
// display files
|
||||
this.viewmode = 1; // TODO take from cookies?
|
||||
this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').removeClass('checked')
|
||||
this.filemanager.all('.fp-vb-icons').addClass('checked')
|
||||
this.refresh(this.currentpath); // MDL-31113 get latest list from server
|
||||
},
|
||||
|
||||
@ -120,7 +145,18 @@ M.form_filemanager.init = function(Y, options) {
|
||||
alert('IO FATAL');
|
||||
return;
|
||||
}
|
||||
var data = Y.JSON.parse(o.responseText);
|
||||
var data = null;
|
||||
try {
|
||||
data = Y.JSON.parse(o.responseText);
|
||||
} catch(e) {
|
||||
// TODO display error
|
||||
//scope.print_msg(M.str.repository.invalidjson, 'error');
|
||||
//scope.display_error(M.str.repository.invalidjson+'<pre>'+stripHTML(o.responseText)+'</pre>', 'invalidjson')
|
||||
return;
|
||||
}
|
||||
if (data && data.tree && scope.set_current_tree) {
|
||||
scope.set_current_tree(data.tree);
|
||||
}
|
||||
args.callback(id,data,p);
|
||||
}
|
||||
},
|
||||
@ -177,9 +213,9 @@ M.form_filemanager.init = function(Y, options) {
|
||||
}, true);
|
||||
},
|
||||
setup_buttons: function() {
|
||||
var button_download = this.filemanager.one('.fm-btn-download');
|
||||
var button_create = this.filemanager.one('.fm-btn-mkdir');
|
||||
var button_addfile = this.filemanager.one('.fm-btn-add');
|
||||
var button_download = this.filemanager.one('.fp-btn-download');
|
||||
var button_create = this.filemanager.one('.fp-btn-mkdir');
|
||||
var button_addfile = this.filemanager.one('.fp-btn-add');
|
||||
|
||||
// setup 'add file' button
|
||||
// if maxfiles == -1, the no limit
|
||||
@ -263,484 +299,428 @@ M.form_filemanager.init = function(Y, options) {
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
},
|
||||
render: function() {
|
||||
var options = this.options;
|
||||
var path = this.options.path;
|
||||
var list = this.options.list;
|
||||
var breadcrumb = this.filemanager.one('.fm-breadcrumb');
|
||||
// empty breadcrumb
|
||||
breadcrumb.set('innerHTML', '').addClass('fm-empty');
|
||||
// build breadcrumb
|
||||
if (path && path.length) {
|
||||
breadcrumb.removeClass('fm-empty');
|
||||
var count = 0;
|
||||
for(var p in path) {
|
||||
var arrow = '';
|
||||
if (count==0) {
|
||||
arrow = Y.Node.create('<span>'+M.str.moodle.path + ': </span>');
|
||||
} else {
|
||||
arrow = Y.Node.create('<span> ▶ </span>');
|
||||
|
||||
this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').
|
||||
on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var viewbar = this.filemanager.one('.fp-viewbar')
|
||||
if (!viewbar || !viewbar.hasClass('disabled')) {
|
||||
this.filemanager.all('.fp-vb-icons,.fp-vb-tree,.fp-vb-details').removeClass('checked')
|
||||
if (e.currentTarget.hasClass('fp-vb-tree')) {
|
||||
this.viewmode = 2;
|
||||
} else if (e.currentTarget.hasClass('fp-vb-details')) {
|
||||
this.viewmode = 3;
|
||||
} else {
|
||||
this.viewmode = 1;
|
||||
}
|
||||
e.currentTarget.addClass('checked')
|
||||
this.render();
|
||||
//Y.Cookie.set('recentviewmode', this.viewmode);
|
||||
}
|
||||
count++;
|
||||
|
||||
var pathid = 'fm-path-node-'+this.client_id;
|
||||
pathid += ('-'+count);
|
||||
|
||||
var crumb = Y.Node.create('<a href="###" id="'+pathid+'">'+path[p].name+'</a>');
|
||||
breadcrumb.appendChild(arrow);
|
||||
breadcrumb.appendChild(crumb);
|
||||
|
||||
var args = {};
|
||||
args.requestpath = path[p].path;
|
||||
args.client_id = this.client_id;
|
||||
Y.one('#'+pathid).on('click', function(e, args) {
|
||||
var scope = this;
|
||||
var params = {};
|
||||
params['filepath'] = args.requestpath;
|
||||
this.currentpath = args.requestpath;
|
||||
this.request({
|
||||
action: 'list',
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.filecount = obj.filecount;
|
||||
scope.check_buttons();
|
||||
scope.options = obj;
|
||||
scope.render(obj);
|
||||
}
|
||||
}, true);
|
||||
}, this, args);
|
||||
}, this);
|
||||
},
|
||||
print_path: function() {
|
||||
var p = this.options.path;
|
||||
this.pathbar.setContent('').addClass('empty');
|
||||
if (p && p.length!=0 && this.viewmode != 2) {
|
||||
for(var i = 0; i < p.length; i++) {
|
||||
var el = this.pathnode.cloneNode(true);
|
||||
this.pathbar.appendChild(el);
|
||||
if (i == 0) {el.addClass('first');}
|
||||
if (i == p.length-1) {el.addClass('last');}
|
||||
if (i%2) {el.addClass('even');} else {el.addClass('odd');}
|
||||
el.one('.fp-path-folder-name').setContent(p[i].name).
|
||||
on('click', function(e, path) {
|
||||
e.preventDefault();
|
||||
var scope = this;
|
||||
this.currentpath = path;
|
||||
this.request({
|
||||
action: 'list',
|
||||
scope: scope,
|
||||
params: {filepath:path},
|
||||
callback: function(id, obj, args) {
|
||||
scope.filecount = obj.filecount;
|
||||
scope.check_buttons();
|
||||
scope.options = obj;
|
||||
scope.render(obj);
|
||||
}
|
||||
}, true);
|
||||
}, this, p[i].path);
|
||||
}
|
||||
this.pathbar.removeClass('empty');
|
||||
}
|
||||
},
|
||||
get_filepath: function(obj) {
|
||||
if (obj.path && obj.path.length) {
|
||||
return obj.path[obj.path.length-1].path;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
treeview_dynload: function(node, cb) {
|
||||
var retrieved_children = {};
|
||||
if (node.children) {
|
||||
for (var i in node.children) {
|
||||
retrieved_children[node.children[i].path] = node.children[i];
|
||||
}
|
||||
}
|
||||
var listhtml = '';
|
||||
|
||||
// folder list items
|
||||
var folder_ids = [];
|
||||
var folder_data = {};
|
||||
|
||||
// normal file list items
|
||||
var file_ids = [];
|
||||
var file_data = {};
|
||||
|
||||
// archives list items
|
||||
var zip_ids = [];
|
||||
var zip_data = {};
|
||||
|
||||
var html_ids = [];
|
||||
var html_data = {};
|
||||
|
||||
file_data.itemid = folder_data.itemid = zip_data.itemid = options.itemid;
|
||||
file_data.client_id = folder_data.client_id = zip_data.client_id = this.client_id;
|
||||
|
||||
var foldername_ids = [];
|
||||
this.request({
|
||||
action:'list',
|
||||
params: {filepath:node.path?node.path:''},
|
||||
scope:this,
|
||||
callback: function(id, obj, args) {
|
||||
var list = obj.list;
|
||||
var scope = args.scope;
|
||||
// check that user did not leave the view mode before recieving this response
|
||||
if (!(scope.viewmode == 2 && node && node.getChildrenEl())) {
|
||||
return;
|
||||
}
|
||||
if (cb != null) { // (in manual mode do not update current path)
|
||||
scope.options = obj;
|
||||
}
|
||||
node.highlight(false);
|
||||
node.origlist = obj.list?obj.list:null;
|
||||
node.origpath = obj.path?obj.path:null;
|
||||
node.children = [];
|
||||
for(k in list) {
|
||||
if (list[k].type == 'folder' && retrieved_children[list[k].filepath]) {
|
||||
// if this child is a folder and has already been retrieved
|
||||
node.children[node.children.length] = retrieved_children[list[k].filepath];
|
||||
} else {
|
||||
// append new file to the list
|
||||
scope.view_files([list[k]]);
|
||||
}
|
||||
}
|
||||
if (cb == null) {
|
||||
node.refresh();
|
||||
} else {
|
||||
// invoke callback requested by TreeView component
|
||||
cb();
|
||||
}
|
||||
//scope.content_scrolled();
|
||||
}
|
||||
}, false);
|
||||
},
|
||||
view_files: function(appendfiles) {
|
||||
this.filemanager.removeClass('fm-updating').removeClass('fm-noitems');
|
||||
if (!list || list.length == 0) {
|
||||
if ((appendfiles == null) && (!this.options.list || this.options.list.length == 0)) {
|
||||
this.filemanager.addClass('fm-noitems');
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
for(var i in list) {
|
||||
count++;
|
||||
// the li html element
|
||||
var htmlid = 'fileitem-'+this.client_id+'-'+count;
|
||||
// link to file
|
||||
var fileid = 'filename-'+this.client_id+'-'+count;
|
||||
// file menu
|
||||
var action = 'action-' +this.client_id+'-'+count;
|
||||
|
||||
var html = M.form_filemanager.templates.onefile;
|
||||
|
||||
html_ids.push('#'+htmlid);
|
||||
html_data[htmlid] = action;
|
||||
|
||||
list[i].htmlid = htmlid;
|
||||
list[i].fileid = fileid;
|
||||
list[i].action = action;
|
||||
|
||||
var url = "###";
|
||||
|
||||
switch (list[i].type) {
|
||||
case 'folder':
|
||||
// click folder name
|
||||
foldername_ids.push('#'+fileid);
|
||||
// click folder menu
|
||||
folder_ids.push('#'+action);
|
||||
folder_data[action] = list[i];
|
||||
folder_data[fileid] = list[i];
|
||||
break;
|
||||
case 'file':
|
||||
file_ids.push('#'+action);
|
||||
// click file name
|
||||
file_ids.push('#'+fileid);
|
||||
file_data[action] = list[i];
|
||||
file_data[fileid] = list[i];
|
||||
if (list[i].url) {
|
||||
url = list[i].url;
|
||||
}
|
||||
break;
|
||||
case 'zip':
|
||||
zip_ids.push('#'+action);
|
||||
zip_ids.push('#'+fileid);
|
||||
zip_data[action] = list[i];
|
||||
zip_data[fileid] = list[i];
|
||||
if (list[i].url) {
|
||||
url = list[i].url;
|
||||
}
|
||||
break;
|
||||
var list = (appendfiles != null) ? appendfiles : this.options.list;
|
||||
var element_template;
|
||||
if (this.viewmode == 2 || this.viewmode == 3) {
|
||||
element_template = Y.Node.create(M.form_filemanager.templates.listfilename);
|
||||
} else {
|
||||
this.viewmode = 1;
|
||||
element_template = Y.Node.create(M.form_filemanager.templates.iconfilename);
|
||||
}
|
||||
var options = {
|
||||
viewmode : this.viewmode,
|
||||
appendonly : appendfiles != null,
|
||||
filenode : element_template,
|
||||
callbackcontext : this,
|
||||
callback : function(e, node) {
|
||||
e.preventDefault();
|
||||
if (node.type == 'folder') {
|
||||
this.refresh(node.filepath);
|
||||
} else {
|
||||
this.select_file(node);
|
||||
}
|
||||
},
|
||||
rightclickcallback : function(e, node) {
|
||||
this.select_file(node);
|
||||
e.preventDefault();
|
||||
}
|
||||
var fullname = list[i].fullname;
|
||||
};
|
||||
if (this.viewmode == 2) {
|
||||
options.dynload = true;
|
||||
options.filepath = this.options.path;
|
||||
options.treeview_dynload = this.treeview_dynload;
|
||||
options.callback = function(e, node) {
|
||||
if (node.type != 'folder') {
|
||||
if (e.node.parent && e.node.parent.origpath) {
|
||||
// set the current path
|
||||
this.options.path = e.node.parent.origpath;
|
||||
this.options.list = e.node.parent.origlist;
|
||||
this.print_path();
|
||||
}
|
||||
this.select_file(node);
|
||||
} else {
|
||||
// save current path and filelist (in case we want to jump to other viewmode)
|
||||
this.options.path = e.node.origpath;
|
||||
this.options.list = e.node.origlist;
|
||||
this.print_path();
|
||||
//this.content_scrolled();
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!this.lazyloading) {this.lazyloading={};}
|
||||
this.filemanager.one('.fp-content').fp_display_filelist(options, list, this.lazyloading);
|
||||
},
|
||||
populate_licenses_select: function(node) {
|
||||
if (!node) {return;}
|
||||
node.setContent('');
|
||||
var licenses = this.options.licenses;
|
||||
for (var i in licenses) {
|
||||
var option = Y.Node.create('<option/>').
|
||||
set('value', licenses[i].shortname).
|
||||
setContent(licenses[i].fullname);
|
||||
node.appendChild(option)
|
||||
}
|
||||
},
|
||||
set_current_tree: function(tree) {
|
||||
var appendfilepaths = function(list, node) {
|
||||
if (!node || !node.children || !node.children.length) {return;}
|
||||
for (var i in node.children) {
|
||||
list[list.length] = node.children[i].filepath;
|
||||
appendfilepaths(list, node.children[i]);
|
||||
}
|
||||
}
|
||||
var list = ['/'];
|
||||
appendfilepaths(list, tree);
|
||||
var selectnode = this.filemanager.one('.fp-select');
|
||||
node = selectnode.one('.fp-path select');
|
||||
node.setContent('');
|
||||
for (var i in list) {
|
||||
node.appendChild(Y.Node.create('<option/>').
|
||||
set('value', list[i]).setContent(list[i]))
|
||||
}
|
||||
},
|
||||
update_file: function() {
|
||||
var selectnode = this.filemanager.one('.fp-select');
|
||||
var fileinfo = this.selectui.fileinfo;
|
||||
|
||||
if (list[i].sortorder == 1) {
|
||||
html = html.replace('___fullname___', '<strong><a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a></strong>');
|
||||
var newfilename = selectnode.one('.fp-saveas input').get('value');
|
||||
var filenamechanged = (newfilename && newfilename != fileinfo.fullname);
|
||||
var pathselect = selectnode.one('.fp-path select'),
|
||||
pathindex = pathselect.get('selectedIndex'),
|
||||
targetpath = pathselect.get("options").item(pathindex).get('value');
|
||||
var filepathchanged = (targetpath != this.get_parent_folder_name(fileinfo));
|
||||
|
||||
if (filenamechanged && filepathchanged) {
|
||||
alert('Sorry, simultaneous changing of name and path is not supported yet'); // TODO
|
||||
return;
|
||||
}
|
||||
if (!filenamechanged && !filepathchanged) {
|
||||
// no changes
|
||||
this.selectui.hide();
|
||||
}
|
||||
|
||||
selectnode.addClass('loading');
|
||||
|
||||
// RENAME
|
||||
if (filenamechanged) {
|
||||
var action = '';
|
||||
var params = {};
|
||||
if (fileinfo.type == 'folder') {
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = '.';
|
||||
params['newdirname'] = newfilename;
|
||||
action = 'renamedir';
|
||||
} else {
|
||||
html = html.replace('___fullname___', '<a title="'+fullname+'" href="'+url+'" id="'+fileid+'"><img src="'+list[i].icon+'" /> ' + fullname + '</a>');
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
params['newfilename'] = newfilename;
|
||||
action = 'rename';
|
||||
}
|
||||
html = html.replace('___action___', '<span class="fm-menuicon" id="'+action+'"><img alt="▶" src="'+M.util.image_url('i/menu')+'" /></span>');
|
||||
html = '<li id="'+htmlid+'">'+html+'</li>';
|
||||
listhtml += html;
|
||||
}
|
||||
this.filemanager.one('.fm-filelist').set('innerHTML', listhtml);
|
||||
|
||||
// click normal file menu
|
||||
Y.on('click', this.create_filemenu, file_ids, this, file_data);
|
||||
Y.on('contextmenu', this.create_filemenu, file_ids, this, file_data);
|
||||
// click folder menu
|
||||
Y.on('click', this.create_foldermenu, folder_ids, this, folder_data);
|
||||
Y.on('contextmenu', this.create_foldermenu, folder_ids, this, folder_data);
|
||||
Y.on('contextmenu', this.create_foldermenu, foldername_ids, this, folder_data);
|
||||
// click archievs menu
|
||||
Y.on('click', this.create_zipmenu, zip_ids, this, zip_data);
|
||||
Y.on('contextmenu', this.create_zipmenu, zip_ids, this, zip_data);
|
||||
// click folder name
|
||||
Y.on('click', this.enter_folder, foldername_ids, this, folder_data);
|
||||
},
|
||||
enter_folder: function(e, data) {
|
||||
var node = e.currentTarget;
|
||||
var file = data[node.get('id')];
|
||||
e.preventDefault();
|
||||
this.refresh(file.filepath);
|
||||
},
|
||||
create_filemenu: function(e, data) {
|
||||
e.preventDefault();
|
||||
var options = this.options;
|
||||
var node = e.currentTarget;
|
||||
var file = data[node.get('id')];
|
||||
var scope = this;
|
||||
|
||||
var menuitems = [
|
||||
{text: M.str.moodle.download, onclick:{fn:open_file_in_new_window, obj:file, scope:this}}
|
||||
];
|
||||
function setmainfile(type, ev, obj) {
|
||||
var file = obj[node.get('id')];
|
||||
//Y.one(mainid).set('value', file.filepath+file.filename);
|
||||
var params = {};
|
||||
params['filepath'] = file.filepath;
|
||||
params['filename'] = file.filename;
|
||||
this.request({
|
||||
action: 'setmainfile',
|
||||
scope: scope,
|
||||
action: action,
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.refresh(scope.currentpath);
|
||||
args.scope.selectui.hide();
|
||||
if (obj == false) {
|
||||
alert(M.str.repository.fileexists); // TODO!
|
||||
} else {
|
||||
args.scope.refresh(obj.filepath);
|
||||
if (typeof M.core_formchangechecker != 'undefined') {
|
||||
M.core_formchangechecker.set_form_changed();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function open_file_in_new_window(type, ev, obj) {
|
||||
// We open in a new window rather than changing the current windows URL as we don't
|
||||
// want to navigate away from the page
|
||||
window.open(obj.url, 'fm-download-file');
|
||||
}
|
||||
if (this.enablemainfile && (file.sortorder != 1)) {
|
||||
var mainid = '#id_'+this.enablemainfile;
|
||||
var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
|
||||
menuitems.push(menu);
|
||||
}
|
||||
this.create_menu(e, 'filemenu', menuitems, file, data);
|
||||
},
|
||||
create_foldermenu: function(e, data) {
|
||||
e.preventDefault();
|
||||
var scope = this;
|
||||
var node = e.currentTarget;
|
||||
var fileinfo = data[node.get('id')];
|
||||
// an extra menu item for folder to zip it
|
||||
function archive_folder(type,ev,obj) {
|
||||
var params = {};
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = '.';
|
||||
this.request({
|
||||
action: 'zip',
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.refresh(obj.filepath);
|
||||
}
|
||||
});
|
||||
}
|
||||
var menuitems = [
|
||||
{text: M.str.editor.zip, onclick: {fn: archive_folder, obj: data, scope: this}},
|
||||
];
|
||||
this.create_menu(e, 'foldermenu', menuitems, fileinfo, data);
|
||||
},
|
||||
create_zipmenu: function(e, data) {
|
||||
e.preventDefault();
|
||||
var scope = this;
|
||||
var node = e.currentTarget;
|
||||
var fileinfo = data[node.get('id')];
|
||||
|
||||
function unzip(type, ev, obj) {
|
||||
// MOVE
|
||||
if (filepathchanged) {
|
||||
var params = {};
|
||||
if (fileinfo.type == 'folder') {
|
||||
action = 'movedir';
|
||||
} else {
|
||||
action = 'movefile';
|
||||
}
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
params['newfilepath'] = targetpath;
|
||||
this.request({
|
||||
action: 'unzip',
|
||||
scope: scope,
|
||||
action: action,
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.refresh(obj.filepath);
|
||||
args.scope.selectui.hide();
|
||||
args.scope.refresh((obj && obj.filepath) ? obj.filepath : '/');
|
||||
if (typeof M.core_formchangechecker != 'undefined') {
|
||||
M.core_formchangechecker.set_form_changed();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
var menuitems = [
|
||||
{text: M.str.moodle.download, url:fileinfo.url},
|
||||
{text: M.str.moodle.unzip, onclick: {fn: unzip, obj: data, scope: this}}
|
||||
];
|
||||
function setmainfile(type, ev, obj) {
|
||||
var file = obj[node.get('id')];
|
||||
//Y.one(mainid).set('value', file.filepath+file.filename);
|
||||
var params = {};
|
||||
params['filepath'] = file.filepath;
|
||||
params['filename'] = file.filename;
|
||||
this.request({
|
||||
action: 'setmainfile',
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.refresh(scope.currentpath);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.enablemainfile && (fileinfo.sortorder != 1)) {
|
||||
var mainid = '#id_'+this.enablemainfile;
|
||||
var menu = {text: M.str.repository.setmainfile, onclick:{fn: setmainfile, obj:data, scope:this}};
|
||||
menuitems.push(menu);
|
||||
}
|
||||
this.create_menu(e, 'zipmenu', menuitems, fileinfo, data);
|
||||
},
|
||||
create_menu: function(ev, menuid, menuitems, fileinfo, options) {
|
||||
var position = [ev.pageX, ev.pageY];
|
||||
var scope = this;
|
||||
function remove(type, ev, obj) {
|
||||
setup_select_file: function() {
|
||||
var selectnode = this.filemanager.one('.fp-select');
|
||||
// bind labels with corresponding inputs
|
||||
selectnode.all('.fp-saveas,.fp-path,.fp-author,.fp-license').each(function (node) {
|
||||
node.all('label').set('for', node.one('input,select').generateID());
|
||||
});
|
||||
this.populate_licenses_select(selectnode.one('.fp-license select'));
|
||||
// register event on clicking buttons
|
||||
selectnode.one('.fp-file-update').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
this.update_file();
|
||||
}, this);
|
||||
selectnode.one('.fp-file-download').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
window.open(this.selectui.fileinfo.url, 'fm-download-file');
|
||||
}, this);
|
||||
selectnode.one('.fp-file-delete').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var dialog_options = {};
|
||||
var params = {};
|
||||
dialog_options.message = M.str.repository.confirmdeletefile;
|
||||
dialog_options.scope = this;
|
||||
var filename = '';
|
||||
var filepath = '';
|
||||
if (fileinfo.type == 'folder') {
|
||||
if (this.selectui.fileinfo.type == 'folder') {
|
||||
params.filename = '.';
|
||||
params.filepath = fileinfo.filepath;
|
||||
params.filepath = this.selectui.fileinfo.filepath;
|
||||
} else {
|
||||
params.filename = fileinfo.fullname;
|
||||
params.filename = this.selectui.fileinfo.fullname;
|
||||
}
|
||||
dialog_options.callbackargs = [params];
|
||||
dialog_options.callback = function(params) {
|
||||
//selectnode.addClass('loading');
|
||||
this.request({
|
||||
action: 'delete',
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
scope.filecount--;
|
||||
scope.refresh(obj.filepath);
|
||||
//args.scope.selectui.hide();
|
||||
args.scope.filecount--;
|
||||
args.scope.refresh(obj.filepath);
|
||||
if (typeof M.core_formchangechecker != 'undefined') {
|
||||
M.core_formchangechecker.set_form_changed();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
M.util.show_confirm_dialog(ev, dialog_options);
|
||||
}
|
||||
function rename (type, ev, obj) {
|
||||
var scope = this;
|
||||
var perform = function(e) {
|
||||
var newfilename = Y.one('#fm-rename-input').get('value');
|
||||
if (!newfilename) {
|
||||
return;
|
||||
this.selectui.hide(); // TODO remove this after confirm dialog is replaced with YUI3
|
||||
M.util.show_confirm_dialog(e, dialog_options);
|
||||
}, this);
|
||||
selectnode.one('.fp-file-zip').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var params = {};
|
||||
var fileinfo = this.selectui.fileinfo;
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = '.';
|
||||
selectnode.addClass('loading');
|
||||
this.request({
|
||||
action: 'zip',
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
args.scope.selectui.hide();
|
||||
args.scope.refresh(obj.filepath);
|
||||
}
|
||||
|
||||
var action = '';
|
||||
var params = {};
|
||||
if (fileinfo.type == 'folder') {
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = '.';
|
||||
params['newdirname'] = newfilename;
|
||||
action = 'renamedir';
|
||||
} else {
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
params['newfilename'] = newfilename;
|
||||
action = 'rename';
|
||||
}
|
||||
scope.request({
|
||||
action: action,
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
if (obj == false) {
|
||||
alert(M.str.repository.fileexists);
|
||||
} else {
|
||||
scope.refresh(obj.filepath);
|
||||
if (typeof M.core_formchangechecker != 'undefined') {
|
||||
M.core_formchangechecker.set_form_changed();
|
||||
}
|
||||
}
|
||||
Y.one('#fm-rename-input').set('value', '');
|
||||
scope.rename_dialog.hide();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
var dialog = Y.one('#fm-rename-dlg');
|
||||
if (!dialog) {
|
||||
dialog = Y.Node.create('<div id="fm-rename-dlg"><div class="hd">'+M.str.repository.enternewname+'</div><div class="bd"><input type="text" id="fm-rename-input" /></div></div>');
|
||||
Y.one(document.body).appendChild(dialog);
|
||||
this.rename_dialog = new YAHOO.widget.Dialog("fm-rename-dlg", {
|
||||
width: "300px",
|
||||
fixedcenter: true,
|
||||
visible: true,
|
||||
constraintoviewport : true
|
||||
});
|
||||
|
||||
}
|
||||
var buttons = [ { text:M.str.moodle.rename, handler:perform, isDefault:true},
|
||||
{ text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
|
||||
|
||||
this.rename_dialog.cfg.queueProperty('buttons', buttons);
|
||||
this.rename_dialog.render();
|
||||
this.rename_dialog.show();
|
||||
//var k1 = new YAHOO.util.KeyListener(scope, {keys:13}, {fn:function(){perform();}, correctScope: true});
|
||||
//k1.enable();
|
||||
Y.one('#fm-rename-input').set('value', fileinfo.fullname);
|
||||
}
|
||||
function move(type, ev, obj) {
|
||||
var scope = this;
|
||||
var itemid = this.options.itemid;
|
||||
// setup move file dialog
|
||||
var dialog = null;
|
||||
if (!Y.one('#fm-move-dlg')) {
|
||||
dialog = Y.Node.create('<div id="fm-move-dlg"></div>');
|
||||
Y.one(document.body).appendChild(dialog);
|
||||
} else {
|
||||
dialog = Y.one('#fm-move-dlg');
|
||||
}
|
||||
|
||||
dialog.set('innerHTML', '<div class="hd">'+M.str.repository.moving+'</div><div class="bd"><div id="fm-move-div">'+M.str.repository.nopathselected+'</div><div id="fm-tree"></div></div>');
|
||||
|
||||
this.movefile_dialog = new YAHOO.widget.Dialog("fm-move-dlg", {
|
||||
width : "600px",
|
||||
fixedcenter : true,
|
||||
visible : false,
|
||||
constraintoviewport : true
|
||||
});
|
||||
|
||||
var treeview = new YAHOO.widget.TreeView("fm-tree");
|
||||
|
||||
var dialog = this.movefile_dialog;
|
||||
function _move(e) {
|
||||
if (!treeview.targetpath) {
|
||||
return;
|
||||
}
|
||||
var params = {};
|
||||
if (fileinfo.type == 'folder') {
|
||||
action = 'movedir';
|
||||
} else {
|
||||
action = 'movefile';
|
||||
}
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
params['newfilepath'] = treeview.targetpath;
|
||||
scope.request({
|
||||
action: action,
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
var p = '/';
|
||||
if (obj) {
|
||||
p = obj.filepath;
|
||||
}
|
||||
dialog.cancel();
|
||||
scope.refresh(p);
|
||||
if (typeof M.core_formchangechecker != 'undefined') {
|
||||
M.core_formchangechecker.set_form_changed();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var buttons = [ { text:M.str.moodle.move, handler:_move, isDefault:true },
|
||||
{ text:M.str.moodle.cancel, handler:function(){this.cancel();}}];
|
||||
|
||||
this.movefile_dialog.cfg.queueProperty("buttons", buttons);
|
||||
this.movefile_dialog.render();
|
||||
|
||||
treeview.subscribe("dblClickEvent", function(e) {
|
||||
// update destidatoin folder
|
||||
this.targetpath = e.node.data.path;
|
||||
var title = Y.one('#fm-move-div');
|
||||
title.set('innerHTML', '<strong>"' + this.targetpath + '"</strong> has been selected.');
|
||||
});
|
||||
|
||||
function loadDataForNode(node, onCompleteCallback) {
|
||||
var params = {};
|
||||
params['filepath'] = node.data.path;
|
||||
var obj = {
|
||||
action: 'dir',
|
||||
scope: scope,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
data = obj.children;
|
||||
if (data.length == 0) {
|
||||
// so it is empty
|
||||
} else {
|
||||
for (var i in data) {
|
||||
var textnode = {label: data[i].fullname, path: data[i].filepath, itemid: this.itemid};
|
||||
var tmpNode = new YAHOO.widget.TextNode(textnode, node, false);
|
||||
}
|
||||
}
|
||||
this.oncomplete();
|
||||
}
|
||||
};
|
||||
obj.oncomplete = onCompleteCallback;
|
||||
scope.request(obj);
|
||||
}
|
||||
|
||||
this.movefile_dialog.subscribe('show', function(){
|
||||
var rootNode = treeview.getRoot();
|
||||
treeview.setDynamicLoad(loadDataForNode);
|
||||
treeview.removeChildren(rootNode);
|
||||
var textnode = {label: M.str.moodle.files, path: '/'};
|
||||
var tmpNode = new YAHOO.widget.TextNode(textnode, rootNode, true);
|
||||
treeview.draw();
|
||||
}, this, true);
|
||||
|
||||
this.movefile_dialog.show();
|
||||
}, this);
|
||||
selectnode.one('.fp-file-unzip').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var params = {};
|
||||
var fileinfo = this.selectui.fileinfo;
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
selectnode.addClass('loading');
|
||||
this.request({
|
||||
action: 'unzip',
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
args.scope.selectui.hide();
|
||||
args.scope.refresh(obj.filepath);
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
selectnode.one('.fp-file-setmain').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var params = {};
|
||||
var fileinfo = this.selectui.fileinfo;
|
||||
params['filepath'] = fileinfo.filepath;
|
||||
params['filename'] = fileinfo.fullname;
|
||||
selectnode.addClass('loading');
|
||||
this.request({
|
||||
action: 'setmainfile',
|
||||
scope: this,
|
||||
params: params,
|
||||
callback: function(id, obj, args) {
|
||||
args.scope.selectui.hide();
|
||||
args.scope.refresh(obj.filepath);
|
||||
}
|
||||
});
|
||||
}, this);
|
||||
selectnode.all('.fp-file-cancel').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
// TODO if changed asked to confirm, the same with close button
|
||||
this.selectui.hide();
|
||||
}, this);
|
||||
},
|
||||
get_parent_folder_name: function(node) {
|
||||
if (node.type != 'folder' || node.filepath.length < node.fullname.length+1) { return node.filepath; }
|
||||
var basedir = node.filepath.substr(0, node.filepath.length - node.fullname.length - 1);
|
||||
var lastdir = node.filepath.substr(node.filepath.length - node.fullname.length - 2);
|
||||
if (lastdir == '/' + node.fullname + '/') { return basedir; }
|
||||
return node.filepath;
|
||||
},
|
||||
select_file: function(node) {
|
||||
var selectnode = this.filemanager.one('.fp-select');
|
||||
selectnode.removeClass('loading').removeClass('fp-folder').
|
||||
removeClass('fp-file').removeClass('fp-zip').removeClass('fp-cansetmain');
|
||||
if (node.type == 'folder' || node.type == 'zip') {selectnode.addClass('fp-'+node.type);}
|
||||
else {selectnode.addClass('fp-file');}
|
||||
if (this.enablemainfile && (node.sortorder != 1)) {
|
||||
selectnode.addClass('fp-cansetmain');
|
||||
}
|
||||
var shared_items = [
|
||||
{text: M.str.moodle.rename+'...', onclick: {fn: rename, obj: options, scope: this}},
|
||||
{text: M.str.moodle.move+'...', onclick: {fn: move, obj: options, scope: this}}
|
||||
];
|
||||
// delete is reserve word in Javascript
|
||||
shared_items.push({text: M.str.moodle['delete']+'...', onclick: {fn: remove, obj: options, scope: this}});
|
||||
var menu = new YAHOO.widget.Menu(menuid, {xy:position, clicktohide:true});
|
||||
menu.clearContent();
|
||||
menu.addItems(menuitems);
|
||||
menu.addItems(shared_items);
|
||||
menu.render(document.body);
|
||||
menu.subscribe('hide', function(){
|
||||
this.fireEvent('destroy');
|
||||
this.selectui.fileinfo = node;
|
||||
selectnode.one('.fp-saveas input').set('value', node.fullname);
|
||||
var foldername = this.get_parent_folder_name(node);
|
||||
selectnode.all('.fp-origpath .fp-value').setContent(foldername);
|
||||
selectnode.all('.fp-author input').set('value', node.author);
|
||||
selectnode.all('.fp-license select option[selected]').set('selected', false);
|
||||
selectnode.all('.fp-license select option[value='+node.license+']').set('selected', true);
|
||||
selectnode.all('.fp-path select option[selected]').set('selected', false);
|
||||
selectnode.all('.fp-path select option').each(function(el){
|
||||
if (el.get('value') == foldername) {el.set('selected', true);}
|
||||
});
|
||||
menu.show();
|
||||
selectnode.all('.fp-author input').set('disabled','disabled'); //TODO
|
||||
selectnode.all('.fp-license select').set('disabled','disabled'); //TODO
|
||||
// display static information about a file (when known)
|
||||
var attrs = ['datemodified','datecreated','size','dimensions'];
|
||||
for (var i in attrs) {
|
||||
if (selectnode.one('.fp-'+attrs[i])) {
|
||||
var value = (node[attrs[i]+'_f']) ? node[attrs[i]+'_f'] : (node[attrs[i]] ? node[attrs[i]] : '');
|
||||
selectnode.one('.fp-'+attrs[i]).addClassIf('fp-unknown', ''+value == '')
|
||||
.one('.fp-value').setContent(value);
|
||||
}
|
||||
}
|
||||
// display thumbnail
|
||||
var imgnode = Y.Node.create('<img/>').
|
||||
set('src', node.realthumbnail ? node.realthumbnail : node.thumbnail).
|
||||
setStyle('maxHeight', ''+(node.thumbnail_height ? node.thumbnail_height : 90)+'px').
|
||||
setStyle('maxWidth', ''+(node.thumbnail_width ? node.thumbnail_width : 90)+'px');
|
||||
selectnode.one('.fp-thumbnail').setContent('').appendChild(imgnode);
|
||||
// show panel
|
||||
this.selectui.show();
|
||||
},
|
||||
render: function() {
|
||||
this.print_path();
|
||||
this.view_files();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -290,7 +290,10 @@ class form_filemanager implements renderable {
|
||||
* client_id=>uniqid(),
|
||||
* acepted_types=>'*',
|
||||
* return_types=>FILE_INTERNAL,
|
||||
* context=>$PAGE->context
|
||||
* context=>$PAGE->context,
|
||||
* author=>fullname($USER),
|
||||
* licenses=>array build from $CFG->licenses,
|
||||
* defaultlicense=>$CFG->sitedefaultlicense
|
||||
*/
|
||||
public function __construct(stdClass $options) {
|
||||
global $CFG, $USER, $PAGE;
|
||||
@ -303,8 +306,22 @@ class form_filemanager implements renderable {
|
||||
'client_id'=>uniqid(),
|
||||
'accepted_types'=>'*',
|
||||
'return_types'=>FILE_INTERNAL,
|
||||
'context'=>$PAGE->context
|
||||
'context'=>$PAGE->context,
|
||||
'author'=>fullname($USER),
|
||||
'licenses'=>array()
|
||||
);
|
||||
if (!empty($CFG->licenses)) {
|
||||
$array = explode(',', $CFG->licenses);
|
||||
foreach ($array as $license) {
|
||||
$l = new stdClass();
|
||||
$l->shortname = $license;
|
||||
$l->fullname = get_string($license, 'license');
|
||||
$defaults['licenses'][] = $l;
|
||||
}
|
||||
}
|
||||
if (!empty($CFG->sitedefaultlicense)) {
|
||||
$defaults['defaultlicense'] = $CFG->sitedefaultlicense;
|
||||
}
|
||||
foreach ($defaults as $key=>$value) {
|
||||
if (empty($options->$key)) {
|
||||
$options->$key = $value;
|
||||
|
@ -439,7 +439,7 @@ class page_requirements_manager {
|
||||
case 'core_filepicker':
|
||||
$module = array('name' => 'core_filepicker',
|
||||
'fullpath' => '/repository/filepicker.js',
|
||||
'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io-base', 'io-upload-iframe', 'io-form', 'yui2-menu', 'yui2-treeview', 'yui2-dragdrop', 'panel', 'cookie', 'datatable', 'datatable-sort', 'resize-plugin', 'dd-plugin', 'resize-constrain'),
|
||||
'requires' => array('base', 'node', 'node-event-simulate', 'json', 'async-queue', 'io-base', 'io-upload-iframe', 'io-form', 'yui2-menu', 'yui2-treeview', 'yui2-dragdrop', 'panel', 'cookie', 'datatable', 'datatable-sort', 'resize-plugin', 'dd-plugin', 'moodle-core_filepicker'),
|
||||
// TODO check if those all are really required
|
||||
'strings' => array(array('add', 'repository'), array('back', 'repository'), array('cancel', 'moodle'), array('close', 'repository'),
|
||||
array('cleancache', 'repository'), array('copying', 'repository'), array('date', 'repository'), array('downloadsucc', 'repository'),
|
||||
|
@ -29,6 +29,7 @@ define('AJAX_SCRIPT', true);
|
||||
require('../config.php');
|
||||
require_once($CFG->libdir.'/filelib.php');
|
||||
require_once($CFG->libdir.'/adminlib.php');
|
||||
require_once($CFG->dirroot.'/repository/lib.php');
|
||||
$PAGE->set_context(get_system_context());
|
||||
require_login();
|
||||
if (isguestuser()) {
|
||||
@ -58,10 +59,12 @@ switch ($action) {
|
||||
case 'list':
|
||||
$filepath = optional_param('filepath', '/', PARAM_PATH);
|
||||
|
||||
$data = file_get_drafarea_files($draftid, $filepath);
|
||||
$data = repository::prepare_listing(file_get_drafarea_files($draftid, $filepath));
|
||||
$info = file_get_draft_area_info($draftid);
|
||||
$data->filecount = $info['filecount'];
|
||||
$data->filesize = $info['filesize'];
|
||||
$data->tree = new stdClass();
|
||||
file_get_drafarea_folders($draftid, '/', $data->tree);
|
||||
echo json_encode($data);
|
||||
die;
|
||||
|
||||
@ -73,6 +76,8 @@ switch ($action) {
|
||||
$fs->create_directory($user_context->id, 'user', 'draft', $draftid, file_correct_filepath(file_correct_filepath($filepath).$newdirname));
|
||||
$return = new stdClass();
|
||||
$return->filepath = $filepath;
|
||||
$return->tree = new stdClass();
|
||||
file_get_drafarea_folders($draftid, '/', $return->tree);
|
||||
echo json_encode($return);
|
||||
die;
|
||||
|
||||
@ -190,6 +195,8 @@ switch ($action) {
|
||||
} else {
|
||||
$return->filepath = $newfilepath;
|
||||
}
|
||||
$return->tree = new stdClass();
|
||||
file_get_drafarea_folders($draftid, '/', $return->tree);
|
||||
echo json_encode($return);
|
||||
die;
|
||||
|
||||
@ -277,6 +284,8 @@ switch ($action) {
|
||||
if ($newfile = $file->extract_to_storage($zipper, $user_context->id, 'user', 'draft', $draftid, $filepath, $USER->id)) {
|
||||
$return = new stdClass();
|
||||
$return->filepath = $filepath;
|
||||
$return->tree = new stdClass();
|
||||
file_get_drafarea_folders($draftid, '/', $return->tree);
|
||||
echo json_encode($return);
|
||||
} else {
|
||||
echo json_encode(false);
|
||||
|
@ -42,6 +42,332 @@
|
||||
* this.logindata, cached login form
|
||||
*/
|
||||
|
||||
YUI.add('moodle-core_filepicker', function(Y) {
|
||||
/** help function to extract width/height style as a number, not as a string */
|
||||
Y.Node.prototype.getStylePx = function(attr) {
|
||||
var style = this.getStyle(attr);
|
||||
if (''+style == '0' || ''+style == '0px') {
|
||||
return 0;
|
||||
}
|
||||
var matches = style.match(/^([\d\.]+)px$/)
|
||||
if (matches && parseFloat(matches[1])) {
|
||||
return parseFloat(matches[1]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** if condition is met, the class is added to the node, otherwise - removed */
|
||||
Y.Node.prototype.addClassIf = function(className, condition) {
|
||||
if (condition) {
|
||||
this.addClass(className);
|
||||
} else {
|
||||
this.removeClass(className);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** sets the width(height) of the node considering existing minWidth(minHeight) */
|
||||
Y.Node.prototype.setStyleAdv = function(stylename, value) {
|
||||
var stylenameCap = stylename.substr(0,1).toUpperCase() + stylename.substr(1, stylename.length-1).toLowerCase();
|
||||
this.setStyle(stylename, '' + Math.max(value, this.getStylePx('min'+stylenameCap)) + 'px')
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a list of files (used by filepicker, filemanager) inside the Node
|
||||
*
|
||||
* @param array options
|
||||
* viewmode : 1 - icons, 2 - tree, 3 - table
|
||||
* appendonly : whether fileslist need to be appended instead of replacing the existing content
|
||||
* filenode : Node element that contains template for displaying one file
|
||||
* callback : On click callback. The element of the fileslist array will be passed as argument
|
||||
* rightclickcallback : On right click callback (optional).
|
||||
* callbackcontext : context where callbacks are executed
|
||||
* sortable : whether content may be sortable (in table mode)
|
||||
* dynload : allow dynamic load for tree view
|
||||
* filepath : for pre-building of tree view - the path to the current directory in filepicker format
|
||||
* treeview_dynload : callback to ...
|
||||
* @param array fileslist array of files to show, each array element may have attributes:
|
||||
* title or fullname : file name
|
||||
* shorttitle (optional) : display file name
|
||||
* thumbnail : url of image
|
||||
* icon : url of icon image
|
||||
* thumbnail_width : width of thumbnail, default 90
|
||||
* thumbnail_height : height of thumbnail, default 90
|
||||
* thumbnail_alt : TODO not needed!
|
||||
* description or thumbnail_title : alt text
|
||||
* @param array lazyloading : reference to the array with lazy loading images
|
||||
*/
|
||||
Y.Node.prototype.fp_display_filelist = function(options, fileslist, lazyloading) {
|
||||
var viewmodeclassnames = {1:'fp-iconview', 2:'fp-treeview', 3:'fp-tableview'};
|
||||
var classname = viewmodeclassnames[options.viewmode];
|
||||
var scope = this;
|
||||
/** return whether file is a folder (different attributes in FileManager and FilePicker) */
|
||||
var file_is_folder = function(node) {
|
||||
if (node.children) {return true;}
|
||||
if (node.type && node.type == 'folder') {return true;}
|
||||
return false;
|
||||
};
|
||||
/** return the name of the file (different attributes in FileManager and FilePicker) */
|
||||
var file_get_filename = function(node) {
|
||||
return node.title ? node.title : node.fullname;
|
||||
}
|
||||
/** return display name of the file (different attributes in FileManager and FilePicker) */
|
||||
var file_get_displayname = function(node) {
|
||||
return node.shorttitle ? node.shorttitle : file_get_filename(node);
|
||||
}
|
||||
/** return file description (different attributes in FileManager and FilePicker) */
|
||||
var file_get_description = function(node) {
|
||||
return node.description ? node.description : (node.thumbnail_title ? node.thumbnail_title : file_get_filename(node));
|
||||
}
|
||||
/** help funciton for tree view */
|
||||
var build_tree = function(node, level) {
|
||||
// prepare file name with icon
|
||||
var el = Y.Node.create('<div/>');
|
||||
el.appendChild(options.filenode.cloneNode(true));
|
||||
|
||||
el.one('.fp-filename').setContent(file_get_displayname(node));
|
||||
// TODO add tooltip with node.title or node.thumbnail_title
|
||||
if (file_is_folder(node)) {
|
||||
el.get('children').addClass('fp-folder');
|
||||
}
|
||||
if (node.icon) {
|
||||
el.one('.fp-icon').appendChild(Y.Node.create('<img/>').set('src', node.icon));
|
||||
if (node.realicon) {
|
||||
lazyloading[el.one('.fp-icon img').generateID()] = node.realicon;
|
||||
}
|
||||
}
|
||||
// create node
|
||||
var tmpNode = new YAHOO.widget.HTMLNode(el.getContent(), level, false);
|
||||
if (node.dynamicLoadComplete) {
|
||||
tmpNode.dynamicLoadComplete = true;
|
||||
}
|
||||
tmpNode.fileinfo = node;
|
||||
tmpNode.isLeaf = !file_is_folder(node);
|
||||
if (!tmpNode.isLeaf) {
|
||||
if(node.expanded) {
|
||||
tmpNode.expand();
|
||||
}
|
||||
tmpNode.path = node.path ? node.path : (node.filepath ? node.filepath : '');
|
||||
for(var c in node.children) {
|
||||
build_tree(node.children[c], tmpNode);
|
||||
}
|
||||
}
|
||||
};
|
||||
/** initialize tree view */
|
||||
var initialize_tree_view = function() {
|
||||
var parentid = scope.one('.'+classname).get('id');
|
||||
scope.treeview = new YAHOO.widget.TreeView(parentid);
|
||||
if (options.dynload) {
|
||||
scope.treeview.setDynamicLoad(Y.bind(options.treeview_dynload, options.callbackcontext), 1);
|
||||
}
|
||||
scope.treeview.singleNodeHighlight = true;
|
||||
if (options.filepath && options.filepath.length) {
|
||||
// we just jumped from icon/details view, we need to show all parents
|
||||
// we extract as much information as possible from filepath and filelist
|
||||
// and send additional requests to retrieve siblings for parent folders
|
||||
var mytree = {};
|
||||
var mytreeel = null;
|
||||
for (var i in options.filepath) {
|
||||
if (mytreeel == null) {
|
||||
mytreeel = mytree;
|
||||
} else {
|
||||
mytreeel.children = [{}];
|
||||
mytreeel = mytreeel.children[0];
|
||||
}
|
||||
var pathelement = options.filepath[i];
|
||||
mytreeel.path = pathelement.path;
|
||||
mytreeel.title = pathelement.name;
|
||||
mytreeel.dynamicLoadComplete = true; // we will call it manually
|
||||
mytreeel.expanded = true;
|
||||
}
|
||||
mytreeel.children = fileslist;
|
||||
build_tree(mytree, scope.treeview.getRoot());
|
||||
// manually call dynload for parent elements in the tree so we can load other siblings
|
||||
if (options.dynload) {
|
||||
var root = scope.treeview.getRoot();
|
||||
while (root && root.children && root.children.length) {
|
||||
root = root.children[0];
|
||||
if (root.path == mytreeel.path) {
|
||||
root.origpath = options.filepath;
|
||||
root.origlist = fileslist;
|
||||
} else if (!root.isLeaf && root.expanded) {
|
||||
Y.bind(options.treeview_dynload, options.callbackcontext)(root, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// there is no path information, just display all elements as a list, without hierarchy
|
||||
for(k in fileslist) {
|
||||
build_tree(fileslist[k], scope.treeview.getRoot());
|
||||
}
|
||||
}
|
||||
scope.treeview.subscribe('clickEvent', function(e){
|
||||
e.node.highlight(false);
|
||||
Y.bind(options.callback, options.callbackcontext)(e, e.node.fileinfo);
|
||||
});
|
||||
if (options.rightclickcallback) {
|
||||
scope.treeview.subscribe('dblClickEvent', function(e){ // TODO right click!
|
||||
e.node.highlight(false);
|
||||
if (e.node.path != '/') {
|
||||
Y.bind(options.rightclickcallback, options.callbackcontext)(e, e.node.fileinfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
scope.treeview.draw();
|
||||
};
|
||||
/** formatting function for table view */
|
||||
var formatValue = function (o){
|
||||
if (o.data[''+o.column.key+'_f_s']) {return o.data[''+o.column.key+'_f_s'];}
|
||||
else if (o.data[''+o.column.key+'_f']) {return o.data[''+o.column.key+'_f'];}
|
||||
else if (o.value) {return o.value;}
|
||||
else {return '';}
|
||||
};
|
||||
/** formatting function for table view */
|
||||
var formatTitle = function(o) {
|
||||
var el = Y.Node.create('<div/>');
|
||||
el.appendChild(options.filenode.cloneNode(true)); // TODO not node but string!
|
||||
if (o.data['isfolder']) {
|
||||
el.get('children').addClass('fp-folder');
|
||||
}
|
||||
el.one('.fp-filename').setContent(o.value);
|
||||
if (o.data['icon']) {
|
||||
el.one('.fp-icon').appendChild(Y.Node.create('<img/>').set('src', o.data['icon']));
|
||||
if (o.data['realicon']) {
|
||||
lazyloading[el.one('.fp-icon img').generateID()] = o.data['realicon'];
|
||||
}
|
||||
}
|
||||
// TODO add tooltip with o.data['title'] (o.value) or o.data['thumbnail_title']
|
||||
return el.getContent();
|
||||
}
|
||||
/** sorting function for table view */
|
||||
var sortFoldersFirst = function(a, b, desc) {
|
||||
if (a.get('isfolder') && !b.get('isfolder')) {return -1;}
|
||||
if (!a.get('isfolder') && b.get('isfolder')) {return 1;}
|
||||
var aa = a.get(this.key), bb = b.get(this.key), dir = desc?-1:1;
|
||||
return (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
|
||||
}
|
||||
/** initialize table view */
|
||||
var initialize_table_view = function() {
|
||||
var parentid = scope.one('.'+classname).get('id');
|
||||
var cols = [
|
||||
{key: "displayname", label: M.str.moodle.name, allowHTML: true, formatter: formatTitle,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "datemodified", label: M.str.moodle.lastmodified, allowHTML: true, formatter: formatValue,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "size", label: M.str.repository.size, allowHTML: true, formatter: formatValue,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "mimetype", label: M.str.repository.type, allowHTML: true,
|
||||
sortable: true, sortFn: sortFoldersFirst}
|
||||
];
|
||||
scope.tableview = new Y.DataTable({columns: cols});
|
||||
scope.tableview.render('#'+parentid);
|
||||
scope.tableview.delegate('click', function (e, tableview) {
|
||||
var record = tableview.getRecord(e.currentTarget.get('id'));
|
||||
if (record) { Y.bind(options.callback, this)(e, record.getAttrs()); }
|
||||
}, 'tr', options.callbackcontext, scope.tableview);
|
||||
if (options.rightclickcallback) {
|
||||
scope.tableview.delegate('contextmenu', function (e, tableview) {
|
||||
var record = tableview.getRecord(e.currentTarget.get('id'));
|
||||
if (record) { Y.bind(options.rightclickcallback, this)(e, record.getAttrs()); }
|
||||
}, 'tr', options.callbackcontext, scope.tableview);
|
||||
}
|
||||
}
|
||||
/** append items in table view mode */
|
||||
var append_files_table = function() {
|
||||
for (var k in fileslist) {
|
||||
// to speed up sorting and formatting
|
||||
fileslist[k].displayname = file_get_displayname(fileslist[k]);
|
||||
fileslist[k].isfolder = file_is_folder(fileslist[k]);
|
||||
}
|
||||
scope.tableview.addRows(fileslist);
|
||||
scope.tableview.sortable = options.sortable ? true : false;
|
||||
};
|
||||
/** append items in tree view mode */
|
||||
var append_files_tree = function() {
|
||||
if (options.appendonly) {
|
||||
var parentnode = scope.treeview.getRoot();
|
||||
if (scope.treeview.getHighlightedNode()) {
|
||||
parentnode = scope.treeview.getHighlightedNode();
|
||||
if (parentnode.isLeaf) {parentnode = parentnode.parent;}
|
||||
}
|
||||
for (var k in fileslist) {
|
||||
build_tree(fileslist[k], parentnode);
|
||||
}
|
||||
scope.treeview.draw();
|
||||
} else {
|
||||
// otherwise files were already added in initialize_tree_view()
|
||||
}
|
||||
}
|
||||
/** append items in icon view mode */
|
||||
var append_files_icons = function() {
|
||||
parent = scope.one('.'+classname);
|
||||
for (var k in fileslist) {
|
||||
var node = fileslist[k];
|
||||
var element = options.filenode.cloneNode(true);
|
||||
parent.appendChild(element);
|
||||
if (file_is_folder(node)) {
|
||||
element.addClass('fp-folder');
|
||||
}
|
||||
var filenamediv = element.one('.fp-filename');
|
||||
filenamediv.setContent(file_get_displayname(node));
|
||||
var imgdiv = element.one('.fp-thumbnail'), width, height, src;
|
||||
if (node.thumbnail) {
|
||||
width = node.thumbnail_width ? node.thumbnail_width : 90;
|
||||
height = node.thumbnail_height ? node.thumbnail_height : 90;
|
||||
src = node.thumbnail;
|
||||
} else {
|
||||
width = 16;
|
||||
height = 16;
|
||||
src = node.icon;
|
||||
}
|
||||
filenamediv.setStyleAdv('width', width);
|
||||
imgdiv.setStyleAdv('width', width).setStyleAdv('height', height);
|
||||
var img = Y.Node.create('<img/>').setAttrs({
|
||||
src: src,
|
||||
title: file_get_description(node),
|
||||
alt: node.thumbnail_alt ? node.thumbnail_alt : file_get_filename(node)}).
|
||||
setStyle('maxWidth', ''+width+'px').
|
||||
setStyle('maxHeight', ''+height+'px');
|
||||
if (node.realthumbnail) {
|
||||
lazyloading[img.generateID()] = node.realthumbnail;
|
||||
}
|
||||
imgdiv.appendChild(img);
|
||||
element.on('click', options.callback, options.callbackcontext, node);
|
||||
if (options.rightclickcallback) {
|
||||
element.on('contextmenu', options.rightclickcallback, options.callbackcontext, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// initialize files view
|
||||
if (!options.appendonly) {
|
||||
var parent = Y.Node.create('<div/>').addClass(classname);
|
||||
this.setContent('').appendChild(parent);
|
||||
parent.generateID();
|
||||
if (options.viewmode == 2) {
|
||||
initialize_tree_view();
|
||||
} else if (options.viewmode == 3) {
|
||||
initialize_table_view();
|
||||
} else {
|
||||
// nothing to initialize for icon view
|
||||
}
|
||||
}
|
||||
|
||||
// append files to the list
|
||||
if (options.viewmode == 2) {
|
||||
append_files_tree();
|
||||
} else if (options.viewmode == 3) {
|
||||
append_files_table();
|
||||
} else {
|
||||
append_files_icons();
|
||||
}
|
||||
|
||||
}
|
||||
}, '@VERSION@', {
|
||||
requires:['base','node'] // TODO TreeView, Table, etc.
|
||||
});
|
||||
|
||||
M.core_filepicker = M.core_filepicker || {};
|
||||
|
||||
/**
|
||||
@ -75,36 +401,6 @@ M.core_filepicker.set_templates = function(Y, templates) {
|
||||
* Add new file picker to current instances
|
||||
*/
|
||||
M.core_filepicker.init = function(Y, options) {
|
||||
/** help function to extract width/height style as a number, not as a string */
|
||||
Y.Node.prototype.getStylePx = function(attr) {
|
||||
var style = this.getStyle(attr);
|
||||
if (''+style == '0' || ''+style == '0px') {
|
||||
return 0;
|
||||
}
|
||||
var matches = style.match(/^([\d\.]+)px$/)
|
||||
if (matches && parseFloat(matches[1])) {
|
||||
return parseFloat(matches[1]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** if condition is met, the class is added to the node, otherwise - removed */
|
||||
Y.Node.prototype.addClassIf = function(className, condition) {
|
||||
if (condition) {
|
||||
this.addClass(className);
|
||||
} else {
|
||||
this.removeClass(className);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/** sets the width(height) of the node considering existing minWidth(minHeight) */
|
||||
Y.Node.prototype.setStyleAdv = function(stylename, value) {
|
||||
var stylenameCap = stylename.substr(0,1).toUpperCase() + stylename.substr(1, stylename.length-1).toLowerCase();
|
||||
this.setStyle(stylename, '' + Math.max(value, this.getStylePx('min'+stylenameCap)) + 'px')
|
||||
return this;
|
||||
}
|
||||
|
||||
var FilePickerHelper = function(options) {
|
||||
FilePickerHelper.superclass.constructor.apply(this, arguments);
|
||||
};
|
||||
@ -378,41 +674,15 @@ M.core_filepicker.init = function(Y, options) {
|
||||
this.fpnode.one('.fp-msg .fp-msg-text').setContent(msg);
|
||||
this.msg_dlg.show();
|
||||
},
|
||||
build_tree: function(node, level) {
|
||||
var dynload = this.active_repo.dynload;
|
||||
// prepare file name with icon
|
||||
var el = Y.Node.create('<div/>').setContent(M.core_filepicker.templates.listfilename);
|
||||
el.one('.fp-filename').setContent(node.shorttitle ? node.shorttitle : node.title);
|
||||
// TODO add tooltip with node.title or node.thumbnail_title
|
||||
if (node.icon && !node.children) {
|
||||
el.one('.fp-icon').appendChild(Y.Node.create('<img/>').set('src', node.icon));
|
||||
if (node.realicon) {
|
||||
this.lazyloading[el.one('.fp-icon img').generateID()] = node.realicon;
|
||||
}
|
||||
}
|
||||
// create node
|
||||
var tmpNode = new YAHOO.widget.HTMLNode(el.getContent(), level, false);
|
||||
if (node.dynamicLoadComplete) {
|
||||
tmpNode.dynamicLoadComplete = true;
|
||||
}
|
||||
tmpNode.fileinfo = node;
|
||||
tmpNode.isLeaf = node.children ? false : true;
|
||||
if (!tmpNode.isLeaf) {
|
||||
if(node.expanded) {
|
||||
tmpNode.expand();
|
||||
}
|
||||
if (dynload) {
|
||||
tmpNode.scope = this;
|
||||
}
|
||||
tmpNode.path = node.path ? node.path : '';
|
||||
for(var c in node.children) {
|
||||
this.build_tree(node.children[c], tmpNode);
|
||||
}
|
||||
}
|
||||
},
|
||||
view_files: function(appenditems) {
|
||||
this.viewbar_set_enabled(true);
|
||||
this.print_path();
|
||||
/*if ((appenditems == null) && (!this.filelist || !this.filelist.length) && !this.active_repo.hasmorepages) {
|
||||
// TODO do it via classes and adjust for each view mode!
|
||||
// If there are no items and no next page, just display status message and quit
|
||||
this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable');
|
||||
return;
|
||||
}*/
|
||||
if (this.viewmode == 2) {
|
||||
this.view_as_list(appenditems);
|
||||
} else if (this.viewmode == 3) {
|
||||
@ -472,23 +742,22 @@ M.core_filepicker.init = function(Y, options) {
|
||||
}, this), 200)
|
||||
},
|
||||
treeview_dynload: function(node, cb) {
|
||||
var scope = node.scope;
|
||||
var client_id = scope.options.client_id;
|
||||
var repository_id = scope.active_repo.id;
|
||||
var retrieved_children = {};
|
||||
if (node.children) {
|
||||
for (var i in node.children) {
|
||||
retrieved_children[node.children[i].path] = node.children[i];
|
||||
}
|
||||
}
|
||||
scope.request({
|
||||
this.request({
|
||||
action:'list',
|
||||
client_id: client_id,
|
||||
repository_id: repository_id,
|
||||
client_id: this.options.client_id,
|
||||
repository_id: this.active_repo.id,
|
||||
path:node.path?node.path:'',
|
||||
page:node.page?args.page:'',
|
||||
scope:this,
|
||||
callback: function(id, obj, args) {
|
||||
var list = obj.list;
|
||||
var scope = args.scope;
|
||||
// check that user did not leave the view mode before recieving this response
|
||||
if (!(scope.active_repo.id == obj.repo_id && scope.viewmode == 2 && node && node.getChildrenEl())) {
|
||||
return;
|
||||
@ -496,8 +765,8 @@ M.core_filepicker.init = function(Y, options) {
|
||||
if (cb != null) { // (in manual mode do not update current path)
|
||||
scope.viewbar_set_enabled(true);
|
||||
scope.parse_repository_options(obj);
|
||||
node.highlight(false);
|
||||
}
|
||||
node.highlight(false);
|
||||
node.origlist = obj.list?obj.list:null;
|
||||
node.origpath = obj.path?obj.path:null;
|
||||
node.children = [];
|
||||
@ -506,13 +775,14 @@ M.core_filepicker.init = function(Y, options) {
|
||||
// if this child is a folder and has already been retrieved
|
||||
node.children[node.children.length] = retrieved_children[list[k].path];
|
||||
} else {
|
||||
scope.build_tree(list[k], node);
|
||||
// append new file to the list
|
||||
scope.view_as_list([list[k]]);
|
||||
}
|
||||
}
|
||||
if (cb == null) {
|
||||
node.refresh();
|
||||
} else {
|
||||
// invoke callback requested by TreeView
|
||||
// invoke callback requested by TreeView component
|
||||
cb();
|
||||
}
|
||||
scope.content_scrolled();
|
||||
@ -523,245 +793,108 @@ M.core_filepicker.init = function(Y, options) {
|
||||
* appends those items to the end of the list. Otherwise (default behaviour)
|
||||
* clears the contents and displays the items from this.filelist */
|
||||
view_as_list: function(appenditems) {
|
||||
var scope = this;
|
||||
var client_id = scope.options.client_id;
|
||||
var dynload = scope.active_repo.dynload;
|
||||
var list = this.filelist;
|
||||
scope.viewmode = 2;
|
||||
if (appenditems) {
|
||||
var parentnode = scope.treeview.getRoot();
|
||||
if (scope.treeview.getHighlightedNode()) {
|
||||
parentnode = scope.treeview.getHighlightedNode();
|
||||
if (parentnode.isLeaf) {parentnode = parentnode.parent;}
|
||||
}
|
||||
for (var k in appenditems) {
|
||||
scope.build_tree(appenditems[k], parentnode);
|
||||
}
|
||||
scope.treeview.draw();
|
||||
return;
|
||||
}
|
||||
if (!list || list.length==0 && (!this.filepath || !this.filepath.length)) {
|
||||
var list = (appenditems != null) ? appenditems : this.filelist;
|
||||
this.viewmode = 2;
|
||||
if (!this.filelist || this.filelist.length==0 && (!this.filepath || !this.filepath.length)) {
|
||||
this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable');
|
||||
return;
|
||||
}
|
||||
|
||||
var treeviewnode = Y.Node.create('<div/>').
|
||||
setAttrs({'class':'fp-treeview', id:'treeview-'+client_id});
|
||||
this.fpnode.one('.fp-content').setContent('').appendChild(treeviewnode);
|
||||
|
||||
scope.treeview = new YAHOO.widget.TreeView('treeview-'+client_id);
|
||||
if (dynload) {
|
||||
scope.treeview.setDynamicLoad(scope.treeview_dynload, 1);
|
||||
}
|
||||
scope.treeview.singleNodeHighlight = true;
|
||||
if (scope.filepath && scope.filepath.length) {
|
||||
// we just jumped from icon/details view, we need to show all parents
|
||||
// we extract as much information as possible from filepath and filelist
|
||||
// and send additional requests to retrieve siblings for parent folders
|
||||
var mytree = {};
|
||||
var mytreeel = null;
|
||||
for (var i in scope.filepath) {
|
||||
if (mytreeel == null) {
|
||||
mytreeel = mytree;
|
||||
} else {
|
||||
mytreeel.children = [{}];
|
||||
mytreeel = mytreeel.children[0];
|
||||
}
|
||||
var parent = scope.filepath[i];
|
||||
mytreeel.path = parent.path;
|
||||
mytreeel.title = parent.name;
|
||||
mytreeel.dynamicLoadComplete = true; // we will call it manually
|
||||
mytreeel.expanded = true;
|
||||
}
|
||||
mytreeel.children = scope.filelist
|
||||
scope.build_tree(mytree, scope.treeview.getRoot());
|
||||
// manually call dynload for parent elements in the tree so we can load other siblings
|
||||
if (dynload) {
|
||||
var root = scope.treeview.getRoot();
|
||||
while (root && root.children && root.children.length) {
|
||||
root = root.children[0];
|
||||
if (root.path == mytreeel.path) {
|
||||
root.origpath = scope.filepath;
|
||||
root.origlist = scope.filelist;
|
||||
} else if (!root.isLeaf && root.expanded) {
|
||||
scope.treeview_dynload(root, null);
|
||||
var element_template = Y.Node.create(M.core_filepicker.templates.listfilename);
|
||||
var options = {
|
||||
viewmode : this.viewmode,
|
||||
appendonly : (appenditems != null),
|
||||
filenode : element_template,
|
||||
callbackcontext : this,
|
||||
callback : function(e, node) {
|
||||
if (!node.children) {
|
||||
if (e.node.parent && e.node.parent.origpath) {
|
||||
// set the current path
|
||||
this.filepath = e.node.parent.origpath;
|
||||
this.filelist = e.node.parent.origlist;
|
||||
this.print_path();
|
||||
}
|
||||
this.select_file(node);
|
||||
} else {
|
||||
// save current path and filelist (in case we want to jump to other viewmode)
|
||||
this.filepath = e.node.origpath;
|
||||
this.filelist = e.node.origlist;
|
||||
this.print_path();
|
||||
this.content_scrolled();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// there is no path information, just display all elements as a list, without hierarchy
|
||||
for(k in list) {
|
||||
scope.build_tree(list[k], scope.treeview.getRoot());
|
||||
}
|
||||
}
|
||||
scope.treeview.subscribe('clickEvent', function(e){
|
||||
e.node.highlight(false);
|
||||
if(e.node.isLeaf){
|
||||
if (e.node.parent && e.node.parent.origpath) {
|
||||
// set the current path
|
||||
scope.filepath = e.node.parent.origpath;
|
||||
scope.filelist = e.node.parent.origlist;
|
||||
scope.print_path();
|
||||
}
|
||||
scope.select_file(e.node.fileinfo);
|
||||
} else {
|
||||
// save current path and filelist (in case we want to jump to other viewmode)
|
||||
scope.filepath = e.node.origpath;
|
||||
scope.filelist = e.node.origlist;
|
||||
scope.print_path();
|
||||
scope.content_scrolled();
|
||||
}
|
||||
});
|
||||
scope.treeview.draw();
|
||||
},
|
||||
dynload : this.active_repo.dynload,
|
||||
filepath : this.filepath,
|
||||
treeview_dynload : this.treeview_dynload
|
||||
};
|
||||
this.fpnode.one('.fp-content').fp_display_filelist(options, list, this.lazyloading);
|
||||
},
|
||||
/** displays list of files in icon view mode. If param appenditems is specified,
|
||||
* appends those items to the end of the list. Otherwise (default behaviour)
|
||||
* clears the contents and displays the items from this.filelist */
|
||||
view_as_icons: function(appenditems) {
|
||||
var scope = this;
|
||||
this.viewmode = 1;
|
||||
var list = this.filelist, container, element_template;
|
||||
if (!appenditems || !this.filelist || !this.filelist.length) {
|
||||
if (!list || list.length==0) {
|
||||
this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable');
|
||||
return;
|
||||
}
|
||||
this.fpnode.one('.fp-content').setContent(M.core_filepicker.templates.iconview);
|
||||
element_template = this.fpnode.one('.fp-content').one('.fp-file');
|
||||
container = element_template.get('parentNode');
|
||||
container.removeChild(element_template);
|
||||
} else {
|
||||
list = appenditems;
|
||||
element_template = Y.Node.create(M.core_filepicker.templates.iconview).one('.fp-file');
|
||||
container = this.fpnode.one('.fp-content').one('.fp-file').get('parentNode')
|
||||
var list = (appenditems != null) ? appenditems : this.filelist;
|
||||
var element_template = Y.Node.create(M.core_filepicker.templates.iconfilename);
|
||||
if ((appenditems == null) && (!this.filelist || !this.filelist.length)) {
|
||||
this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable');
|
||||
return;
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
for(var k in list) {
|
||||
var node = list[k];
|
||||
var element = element_template.cloneNode(true);
|
||||
container.appendChild(element);
|
||||
var filename = node.shorttitle ? node.shorttitle : node.title;
|
||||
var filenamediv = element.one('.fp-filename');
|
||||
filenamediv.setContent(filename);
|
||||
var imgdiv = element.one('.fp-thumbnail');
|
||||
var width = node.thumbnail_width ? node.thumbnail_width : 90;
|
||||
var height = node.thumbnail_height ? node.thumbnail_height : 90;
|
||||
filenamediv.setStyleAdv('width', width);
|
||||
imgdiv.setStyleAdv('width', width).setStyleAdv('height', height);
|
||||
var img = Y.Node.create('<img/>').setAttrs({src:node.thumbnail,title:node.title});
|
||||
if(node.thumbnail_alt) {
|
||||
img.set('alt', node.thumbnail_alt);
|
||||
}
|
||||
if(node.thumbnail_title) {
|
||||
img.set('title', node.thumbnail_title);
|
||||
}
|
||||
img.setStyle('maxWidth', ''+width+'px').setStyle('maxHeight', ''+height+'px');
|
||||
if (node.realthumbnail) {
|
||||
this.lazyloading[img.generateID()] = node.realthumbnail;
|
||||
}
|
||||
imgdiv.appendChild(img)
|
||||
|
||||
var dynload = this.active_repo.dynload;
|
||||
if(node.children) {
|
||||
element.on('click', function(e, p) {
|
||||
e.preventDefault();
|
||||
if(dynload) {
|
||||
scope.list({'path':p.path});
|
||||
}else{
|
||||
this.filepath = p.path;
|
||||
this.filelist = p.children;
|
||||
var options = {
|
||||
viewmode : this.viewmode,
|
||||
appendonly : (appenditems != null),
|
||||
filenode : element_template,
|
||||
callbackcontext : this,
|
||||
callback : function(e, node) {
|
||||
e.preventDefault();
|
||||
if(node.children) {
|
||||
if (this.active_repo.dynload) {
|
||||
this.list({'path':node.path});
|
||||
} else {
|
||||
this.filepath = node.path;
|
||||
this.filelist = node.children;
|
||||
this.view_files();
|
||||
}
|
||||
}, this, node);
|
||||
} else {
|
||||
element.on('click', function(e, args) {
|
||||
e.preventDefault();
|
||||
this.select_file(args);
|
||||
}, this, list[k]);
|
||||
} else {
|
||||
this.select_file(node);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
};
|
||||
this.fpnode.one('.fp-content').fp_display_filelist(options, list, this.lazyloading);
|
||||
},
|
||||
/** displays list of files in table view mode. If param appenditems is specified,
|
||||
* appends those items to the end of the list. Otherwise (default behaviour)
|
||||
* clears the contents and displays the items from this.filelist */
|
||||
view_as_table: function(appenditems) {
|
||||
var list = this.filelist, scope = this;
|
||||
var client_id = this.options.client_id;
|
||||
this.viewmode = 3;
|
||||
if (appenditems != null) {
|
||||
this.tableview.addRows(appenditems);
|
||||
this.tableview.sortable = !this.active_repo.hasmorepages;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!list || list.length==0) {
|
||||
var list = (appenditems != null) ? appenditems : this.filelist;
|
||||
if (!appenditems && (!this.filelist || this.filelist.length==0) && !this.active_repo.hasmorepages) {
|
||||
this.display_error(M.str.repository.nofilesavailable, 'nofilesavailable');
|
||||
return;
|
||||
}
|
||||
var treeviewnode = Y.Node.create('<div/>').
|
||||
setAttrs({'class':'fp-tableview', id:'tableview-'+client_id});
|
||||
this.fpnode.one('.fp-content').setContent('').appendChild(treeviewnode);
|
||||
var formatValue = function (o){
|
||||
if (o.data[''+o.column.key+'_f_s']) { return o.data[''+o.column.key+'_f_s']; }
|
||||
else if (o.data[''+o.column.key+'_f']) { return o.data[''+o.column.key+'_f']; }
|
||||
else if (o.value) { return o.value; }
|
||||
else { return ''; }
|
||||
};
|
||||
var formatTitle = function(o) {
|
||||
var el = Y.Node.create('<div/>').setContent(M.core_filepicker.templates.listfilename);
|
||||
el.one('.fp-filename').setContent(o.data['shorttitle'] ? o.data['shorttitle'] : o.value);
|
||||
el.one('.fp-icon').appendChild(Y.Node.create('<img/>').set('src', o.data['icon']));
|
||||
if (o.data['realicon']) {
|
||||
scope.lazyloading[el.one('.fp-icon img').generateID()] = o.data['realicon'];
|
||||
}
|
||||
// TODO add tooltip with o.data['title'] (o.value) or o.data['thumbnail_title']
|
||||
return el.getContent();
|
||||
}
|
||||
var sortFoldersFirst = function(a, b, desc) {
|
||||
if (a.get('children') && !b.get('children')) {return -1;}
|
||||
if (!a.get('children') && b.get('children')) {return 1;}
|
||||
var aa = a.get(this.key), bb = b.get(this.key), dir = desc?-1:1;
|
||||
if (this.key == 'title' && a.get('shorttitle')) {aa=a.get('shorttitle');}
|
||||
if (this.key == 'title' && b.get('shorttitle')) {bb=b.get('shorttitle');}
|
||||
return (aa > bb) ? dir : ((aa < bb) ? -dir : 0);
|
||||
}
|
||||
|
||||
var cols = [
|
||||
{key: "title", label: M.str.moodle.name, allowHTML: true, formatter: formatTitle,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "datemodified", label: M.str.moodle.lastmodified, allowHTML: true, formatter: formatValue,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "size", label: M.str.repository.size, allowHTML: true, formatter: formatValue,
|
||||
sortable: true, sortFn: sortFoldersFirst},
|
||||
{key: "type", label: M.str.repository.type, allowHTML: true,
|
||||
sortable: true, sortFn: sortFoldersFirst}
|
||||
];
|
||||
this.tableview = new Y.DataTable({
|
||||
columns: cols,
|
||||
data: list,
|
||||
sortable: !this.active_repo.hasmorepages // allow sorting only if there are no more pages to load
|
||||
});
|
||||
|
||||
this.tableview.render('#tableview-'+client_id);
|
||||
this.tableview.delegate('click', function (e) {
|
||||
var record = this.tableview.getRecord(e.currentTarget.get('id'));
|
||||
if (record) {
|
||||
var data = record.getAttrs();
|
||||
if (data.children) {
|
||||
var element_template = Y.Node.create(M.core_filepicker.templates.listfilename);
|
||||
var options = {
|
||||
viewmode : this.viewmode,
|
||||
appendonly : (appenditems != null),
|
||||
filenode : element_template,
|
||||
callbackcontext : this,
|
||||
sortable : !this.active_repo.hasmorepages,
|
||||
callback : function(e, node) {
|
||||
e.preventDefault();
|
||||
if (node.children) {
|
||||
if (this.active_repo.dynload) {
|
||||
this.list({'path':data.path});
|
||||
this.list({'path':node.path});
|
||||
} else {
|
||||
this.filepath = data.path;
|
||||
this.filelist = data.children;
|
||||
this.filepath = node.path;
|
||||
this.filelist = node.children;
|
||||
this.view_files();
|
||||
}
|
||||
} else {
|
||||
this.select_file(data);
|
||||
this.select_file(node);
|
||||
}
|
||||
}
|
||||
}, 'tr', this);
|
||||
};
|
||||
this.fpnode.one('.fp-content').fp_display_filelist(options, list, this.lazyloading);
|
||||
},
|
||||
/** If more than one page available, requests and displays the files from the next page */
|
||||
request_next_page: function() {
|
||||
|
@ -1783,17 +1783,27 @@ abstract class repository {
|
||||
* Prepares list of files before passing it to AJAX, makes sure data is in the correct
|
||||
* format and stores formatted dates.
|
||||
*
|
||||
* @param array $listing result of get_listing() or search()
|
||||
* @param array|stdClass $listing result of get_listing() or search() or file_get_drafarea_files()
|
||||
* @return array
|
||||
*/
|
||||
public static function prepare_listing($listing) {
|
||||
global $OUTPUT;
|
||||
if (!is_array($listing) || !isset($listing['list'])) {
|
||||
if (is_array($listing) && isset($listing['list'])) {
|
||||
$files = &$listing['list'];
|
||||
} else if (is_object($listing) && isset($listing->list)) {
|
||||
$files = &$listing->list;
|
||||
} else {
|
||||
return $listing;
|
||||
}
|
||||
$len = count($listing['list']);
|
||||
$len = count($files);
|
||||
for ($i=0; $i<$len; $i++) {
|
||||
$file = & $listing['list'][$i];
|
||||
if (is_object($files[$i])) {
|
||||
$file = (array)$files[$i];
|
||||
$converttoobject = true;
|
||||
} else {
|
||||
$file = & $files[$i];
|
||||
$converttoobject = false;
|
||||
}
|
||||
if (isset($file['size'])) {
|
||||
$file['size'] = (int)$file['size'];
|
||||
$file['size_f'] = display_size($file['size']);
|
||||
@ -1820,20 +1830,31 @@ abstract class repository {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isset($file['type']) && !array_key_exists('children', $file) && isset($file['title'])) {
|
||||
$mimetype = mimeinfo('type', $file['title']);
|
||||
$isfolder = (array_key_exists('children', $file) || (isset($file['type']) && $file['type'] == 'folder'));
|
||||
$filename = null;
|
||||
if (isset($file['title'])) {
|
||||
$filename = $file['title'];
|
||||
}
|
||||
else if (isset($file['fullname'])) {
|
||||
$filename = $file['fullname'];
|
||||
}
|
||||
if (!isset($file['mimetype']) && !$isfolder && $filename) {
|
||||
$mimetype = mimeinfo('type', $filename);
|
||||
if (get_string_manager()->string_exists($mimetype, 'mimetypes')) {
|
||||
$mimetype = get_string($mimetype, 'mimetypes');
|
||||
}
|
||||
$file['type'] = $mimetype;
|
||||
$file['mimetype'] = $mimetype;
|
||||
}
|
||||
if (!isset($file['icon']) && isset($file['title'])) {
|
||||
if (array_key_exists('children', $file)) {
|
||||
if (!isset($file['icon'])) {
|
||||
if ($isfolder) {
|
||||
$file['icon'] = $OUTPUT->pix_url('f/folder')->out(false);
|
||||
} else {
|
||||
$file['icon'] = $OUTPUT->pix_url('f/'.mimeinfo('icon', $file['title']))->out(false);
|
||||
} else if ($filename) {
|
||||
$file['icon'] = $OUTPUT->pix_url('f/'.mimeinfo('icon', $filename))->out(false);
|
||||
}
|
||||
}
|
||||
if ($converttoobject) {
|
||||
$files[$i] = (object)$file;
|
||||
}
|
||||
}
|
||||
return $listing;
|
||||
}
|
||||
|
@ -221,6 +221,7 @@ class repository_local_file {
|
||||
$node['license'] = $this->fileinfo->get_license();
|
||||
$node['source'] = $encodedpath;
|
||||
$node['thumbnail'] = $OUTPUT->pix_url(file_extension_icon($node['title'], 32))->out(false);
|
||||
$node['realthumbnail'] = $this->fileinfo->get_url();
|
||||
}
|
||||
return $node;
|
||||
}
|
||||
|
@ -2,40 +2,47 @@
|
||||
* File picker
|
||||
*/
|
||||
/* first or middle sibling, no children */
|
||||
.file-picker .ygtvtn {background: url([[pix:moodle|y/tn]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
.file-picker .ygtvtn, .filemanager .ygtvtn {background: url([[pix:moodle|y/tn]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
/* first or middle sibling, collapsable */
|
||||
.file-picker .ygtvtm {background: url([[pix:moodle|y/tm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvtm, .filemanager .ygtvtm {background: url([[pix:moodle|y/tm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* first or middle sibling, collapsable, hover */
|
||||
.file-picker .ygtvtmh {background: url([[pix:moodle|y/tmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvtmh, .filemanager .ygtvtmh {background: url([[pix:moodle|y/tmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* first or middle sibling, expandable */
|
||||
.file-picker .ygtvtp {background: url([[pix:moodle|y/tp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvtp, .filemanager .ygtvtp {background: url([[pix:moodle|y/tp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* first or middle sibling, expandable, hover */
|
||||
.file-picker .ygtvtph {background: url([[pix:moodle|y/tph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvtph, .filemanager .ygtvtph {background: url([[pix:moodle|y/tph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* last sibling, no children */
|
||||
.file-picker .ygtvln {background: url([[pix:moodle|y/ln]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
.file-picker .ygtvln, .filemanager .ygtvln {background: url([[pix:moodle|y/ln]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
/* Last sibling, collapsable */
|
||||
.file-picker .ygtvlm {background: url([[pix:moodle|y/lm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvlm, .filemanager .ygtvlm {background: url([[pix:moodle|y/lm]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* Last sibling, collapsable, hover */
|
||||
.file-picker .ygtvlmh {background: url([[pix:moodle|y/lmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvlmh, .filemanager .ygtvlmh {background: url([[pix:moodle|y/lmh]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* Last sibling, expandable */
|
||||
.file-picker .ygtvlp {background: url([[pix:moodle|y/lp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvlp, .filemanager .ygtvlp {background: url([[pix:moodle|y/lp]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* Last sibling, expandable, hover */
|
||||
.file-picker .ygtvlph {background: url([[pix:moodle|y/lph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
.file-picker .ygtvlph, .filemanager .ygtvlph {background: url([[pix:moodle|y/lph]]) 0 0 no-repeat;width:34px;height:22px;cursor:pointer;}
|
||||
/* Loading icon */
|
||||
.file-picker .ygtvloading {background: url([[pix:moodle|y/loading]]) 0 0 no-repeat;width:16px;height:22px;}
|
||||
.file-picker .ygtvloading, .filemanager .ygtvloading {background: url([[pix:moodle|y/loading]]) 0 0 no-repeat;width:16px;height:22px;}
|
||||
/* the style for the empty cells that are used for rendering the depth* of the node */
|
||||
.file-picker .ygtvdepthcell {background: url([[pix:moodle|y/vline]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
.file-picker .ygtvblankdepthcell {width:17px;height:22px;}
|
||||
.file-picker .ygtvdepthcell, .filemanager .ygtvdepthcell {background: url([[pix:moodle|y/vline]]) 0 0 no-repeat;width:17px;height:22px;}
|
||||
.file-picker .ygtvblankdepthcell, .filemanager .ygtvblankdepthcell {width:17px;height:22px;}
|
||||
/* the style of the div around each node */
|
||||
.file-picker .ygtvitem table{margin-bottom:0;}
|
||||
.file-picker .ygtvitem td {border:none;padding:0;}
|
||||
.file-picker .ygtvitem table, .filemanager .ygtvitem table{margin-bottom:0;}
|
||||
.file-picker .ygtvitem td, .filemanager .ygtvitem td {border:none;padding:0;}
|
||||
/* the style of the div around each node's collection of children */
|
||||
* html .file-picker .ygtvchildren {height:1%;}
|
||||
* html .file-picker .ygtvchildren, * html .filemanager .ygtvchildren {height:1%;}
|
||||
/* the style of the text label in ygTextNode */
|
||||
.file-picker .ygtvlabel,
|
||||
.file-picker .ygtvlabel:link,
|
||||
.file-picker .ygtvlabel:visited,
|
||||
.file-picker .ygtvlabel:hover {margin-left:2px;text-decoration: none;}
|
||||
.file-picker .ygtvlabel:hover,
|
||||
.filemanager .ygtvlabel,
|
||||
.filemanager .ygtvlabel:link,
|
||||
.filemanager .ygtvlabel:visited,
|
||||
.filemanager .ygtvlabel:hover {margin-left:2px;text-decoration: none;}
|
||||
.file-picker .fp-treeview .fp-folder .fp-icon,
|
||||
.filemanager .fp-treeview .fp-folder .fp-icon {display:none;}
|
||||
|
||||
.file-picker {font-size:12px;}
|
||||
.file-picker.fp-generallayout {width:700px;height:480px;}
|
||||
.file-picker strong {background:#FFFFCC;}
|
||||
@ -89,8 +96,8 @@
|
||||
.filemanager-toolbar a {border: 1px solid #AACCEE;background: #F4FAFF;color: black;padding: 3px;}
|
||||
.filemanager-toolbar a:hover {background: #FFFFFF;}
|
||||
.filemanager-toolbar .helplink a {border: 0px; background: transparent;}
|
||||
.fm-breadcrumb {margin:0;}
|
||||
.filemanager .fm-breadcrumb.fm-empty {display:none;}
|
||||
.fp-pathbar {margin:0;}
|
||||
.filemanager .fp-pathbar.empty {display:none;}
|
||||
.filemanager-container {padding: 5px;margin: 6px 0;background: #E9F4FF;border: #AACCEE 1px solid;position: relative;}
|
||||
.filemanager-container ul{margin:0;padding:0;}
|
||||
.filemanager-container ul li{white-space:nowrap;list-style-type:none;}
|
||||
@ -106,27 +113,46 @@
|
||||
.filemanager-container,
|
||||
.filepicker-filelist {overflow:hidden;}
|
||||
|
||||
.filemanager.fm-loading .fm-breadcrumb,
|
||||
.filemanager.fm-loading .fp-pathbar,
|
||||
.filemanager.fm-loading .filemanager-toolbar,
|
||||
.filemanager.fm-loading .filemanager-updating,
|
||||
.filemanager.fm-loading .filemanager-container {display:none;}
|
||||
|
||||
.filemanager.fm-loaded .filemanager-loading {display:none;}
|
||||
|
||||
.filemanager.fm-nofiles .fm-btn-download {display:none;}
|
||||
.filemanager.fm-nofiles .fp-btn-download {display:none;}
|
||||
|
||||
.filemanager.fm-nomkdir .fm-btn-mkdir {display:none;}
|
||||
.filemanager.fm-nomkdir .fp-btn-mkdir {display:none;}
|
||||
|
||||
.filemanager.fm-maxfiles .fm-btn-add {display:none;}
|
||||
.filemanager.fm-maxfiles .fp-btn-add {display:none;}
|
||||
.filemanager.fm-maxfiles .dndupload-message {display:none;}
|
||||
|
||||
.filemanager .fm-empty-container {display:none;}
|
||||
.filemanager.fm-noitems .fm-empty-container {display:block;}
|
||||
.filemanager.fm-noitems .filemanager-container .fm-filelist {display:none;}
|
||||
.filemanager.fm-noitems .filemanager-container .fp-content {display:none;}
|
||||
|
||||
.filemanager .filemanager-updating {display:none;text-align:center;}
|
||||
.filemanager.fm-updating .filemanager-updating {display:block;}
|
||||
.filemanager.fm-updating .filemanager-container {display:none;}
|
||||
.filemanager.fm-updating .fm-content-wrapper {display:none;}
|
||||
.filemanager .fp-iconview .fp-file {float:left;text-align:center;}
|
||||
.filemanager .fp-iconview .fp-file div {overflow: hidden;}
|
||||
.filemanager .fp-iconview .fp-file .fp-filename {height:48px;text-align:center;min-width:50px;}
|
||||
|
||||
.filemanager .fp-select .fp-select-loading {display:none;}
|
||||
.filemanager .fp-select.loading .fp-select-loading {display:block;}
|
||||
.filemanager .fp-select.loading form {display:none;}
|
||||
|
||||
/* disable unavailable actions: */
|
||||
/*.filemanager .fp-select.fp-zip .fp-license,*/
|
||||
.filemanager .fp-select.fp-folder .fp-license,
|
||||
/*.filemanager .fp-select.fp-zip .fp-author,*/
|
||||
.filemanager .fp-select.fp-folder .fp-author,
|
||||
.filemanager .fp-select.fp-file .fp-file-unzip,
|
||||
.filemanager .fp-select.fp-folder .fp-file-unzip,
|
||||
.filemanager .fp-select.fp-file .fp-file-zip,
|
||||
.filemanager .fp-select.fp-zip .fp-file-zip {display:none;}
|
||||
.filemanager .fp-select .fp-file-setmain {display:none;}
|
||||
.filemanager .fp-select.fp-cansetmain .fp-file-setmain {display:inline-block;}
|
||||
.filemanager .fp-select.fp-folder .fp-file-download {display:none;} /* to be implemented */
|
||||
|
||||
/*
|
||||
* Drag and drop support
|
||||
|
Loading…
x
Reference in New Issue
Block a user