Note: "Save as task" dialog for email does not contain Attachments tab, as "Save as event" dialogs. We likely would want attachments handling in this dialog too. Currently it works only in Tasks UI.
2677 lines
76 KiB
JavaScript
2677 lines
76 KiB
JavaScript
/**
|
|
* Kolab files plugin
|
|
*
|
|
* @author Aleksander Machniak <machniak@kolabsys.com>
|
|
*
|
|
* @licstart The following is the entire license notice for the
|
|
* JavaScript code in this file.
|
|
*
|
|
* Copyright (C) 2011, Kolab Systems AG <contact@kolabsys.com>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU Affero General Public License as
|
|
* published by the Free Software Foundation, either version 3 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU Affero General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* @licend The above is the entire license notice
|
|
* for the JavaScript code in this file.
|
|
*/
|
|
|
|
window.rcmail && window.files_api && rcmail.addEventListener('init', function() {
|
|
if (rcmail.task == 'mail') {
|
|
// mail compose
|
|
if (rcmail.env.action == 'compose') {
|
|
kolab_files_from_cloud_widget($('#compose-attachments > div'));
|
|
|
|
// register some commands to skip warning message on compose page
|
|
$.merge(rcmail.env.compose_commands, ['files-list', 'files-sort', 'files-search', 'files-search-reset']);
|
|
}
|
|
// mail preview
|
|
else if (rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
|
|
var attachment_list = $('#attachment-list');
|
|
|
|
if ($('li', attachment_list).length) {
|
|
var link = $('<a href="#" class="button filesaveall">')
|
|
.text(rcmail.gettext('kolab_files.saveall'))
|
|
.click(function() { kolab_directory_selector_dialog(); })
|
|
.insertAfter(attachment_list);
|
|
}
|
|
|
|
rcmail.addEventListener('menu-open', kolab_files_attach_menu_open);
|
|
rcmail.enable_command('folder-create', true);
|
|
}
|
|
// attachment preview
|
|
else if (rcmail.env.action == 'get') {
|
|
rcmail.enable_command('folder-create', true);
|
|
}
|
|
|
|
if (!rcmail.env.action || rcmail.env.action == 'show' || rcmail.env.action == 'preview') {
|
|
// add "attach from cloud" button for event/task dialog in mail
|
|
rcmail.addEventListener('plugin.mail2event_dialog', function() {
|
|
if (!$('#calendar-attachment-form input.fromcloud').length)
|
|
kolab_files_from_cloud_widget($('#calendar-attachment-form > div.formbuttons'));
|
|
});
|
|
}
|
|
|
|
kolab_files_init();
|
|
}
|
|
else if (rcmail.task == 'calendar') {
|
|
// add "attach from cloud" button for event dialog
|
|
if (!rcmail.env.action)
|
|
kolab_files_from_cloud_widget($('#calendar-attachment-form > div.formbuttons'));
|
|
kolab_files_init();
|
|
}
|
|
else if (rcmail.task == 'tasks') {
|
|
// add "attach from cloud" button for task dialog
|
|
if (!rcmail.env.action)
|
|
kolab_files_from_cloud_widget($('#taskedit-attachment-form > div.formbuttons'));
|
|
kolab_files_init();
|
|
}
|
|
else if (rcmail.task == 'files') {
|
|
if (rcmail.gui_objects.filelist) {
|
|
rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, {
|
|
multiselect: true,
|
|
draggable: true,
|
|
keyboard: true,
|
|
column_movable: rcmail.env.col_movable,
|
|
dblclick_time: rcmail.dblclick_time
|
|
});
|
|
|
|
rcmail.file_list.addEventListener('dblclick', function(o) { kolab_files_list_dblclick(o); })
|
|
.addEventListener('select', function(o) { kolab_files_list_select(o); })
|
|
.addEventListener('keypress', function(o) { kolab_files_list_keypress(o); })
|
|
.addEventListener('dragstart', function(e) { kolab_files_drag_start(e); })
|
|
.addEventListener('dragmove', function(e) { kolab_files_drag_move(e); })
|
|
.addEventListener('dragend', function(e) { kolab_files_drag_end(e); })
|
|
.addEventListener('column_replace', function(e) { kolab_files_set_coltypes(e); })
|
|
.addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); });
|
|
|
|
rcmail.enable_command('menu-open', 'menu-save', 'files-sort', 'files-search', 'files-search-reset', 'folder-create', true);
|
|
|
|
rcmail.file_list.init();
|
|
kolab_files_list_coltypes();
|
|
kolab_files_drag_drop_init($(rcmail.gui_objects.filelist).parents('.droptarget'));
|
|
}
|
|
|
|
// "one file only" commands
|
|
rcmail.env.file_commands = ['files-get'];
|
|
// "one or more file" commands
|
|
rcmail.env.file_commands_all = ['files-delete', 'files-move', 'files-copy'];
|
|
|
|
kolab_files_init();
|
|
|
|
if (rcmail.env.action == 'open') {
|
|
rcmail.enable_command('files-get', 'files-delete', rcmail.env.file);
|
|
}
|
|
else {
|
|
file_api.folder_list();
|
|
file_api.browser_capabilities_check();
|
|
rcmail.enable_command('folder-mount', rcmail.env.external_sources);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
/**********************************************************/
|
|
/********* Shared functionality **********/
|
|
/**********************************************************/
|
|
|
|
// Initializes API object
|
|
function kolab_files_init()
|
|
{
|
|
if (window.file_api)
|
|
return;
|
|
|
|
// Initialize application object (don't change var name!)
|
|
file_api = $.extend(new files_api(), new kolab_files_ui());
|
|
|
|
file_api.set_env({
|
|
token: kolab_files_token(),
|
|
url: rcmail.env.files_url,
|
|
sort_col: 'name',
|
|
sort_reverse: false,
|
|
search_threads: rcmail.env.search_threads,
|
|
resources_dir: rcmail.assets_path('program/resources'),
|
|
caps: rcmail.env.files_caps,
|
|
supported_mimetypes: rcmail.env.file_mimetypes
|
|
});
|
|
|
|
file_api.translations = rcmail.labels;
|
|
};
|
|
|
|
// returns API authorization token
|
|
function kolab_files_token()
|
|
{
|
|
// consider the token from parent window more reliable (fresher) than in framed window
|
|
// it's because keep-alive is not requested in frames
|
|
return window.parent && parent.rcmail && parent.rcmail.env.files_token ? parent.rcmail.env.files_token : rcmail.env.files_token;
|
|
};
|
|
|
|
function kolab_files_from_cloud_widget(elem)
|
|
{
|
|
var input = $('<input class="button fromcloud" type="button">')
|
|
.attr('tabindex', $('input', elem).attr('tabindex') || 0)
|
|
.val(rcmail.gettext('kolab_files.fromcloud'))
|
|
.click(function() { kolab_files_selector_dialog(); })
|
|
.appendTo(elem);
|
|
|
|
if (rcmail.gui_objects.filelist) {
|
|
rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, {
|
|
multiselect: true,
|
|
keyboard: true,
|
|
column_movable: false,
|
|
dblclick_time: rcmail.dblclick_time
|
|
});
|
|
rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); })
|
|
.addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); });
|
|
|
|
rcmail.enable_command('files-sort', 'files-search', 'files-search-reset', true);
|
|
|
|
rcmail.file_list.init();
|
|
kolab_files_list_coltypes();
|
|
}
|
|
}
|
|
|
|
// folder selection dialog
|
|
function kolab_directory_selector_dialog(id)
|
|
{
|
|
var dialog = $('#files-dialog'),
|
|
input = $('#file-save-as-input'),
|
|
form = $('#file-save-as'),
|
|
list = $('#folderlistbox'),
|
|
buttons = {}, label = 'saveto',
|
|
win = window, fn;
|
|
|
|
// attachment is specified
|
|
if (id) {
|
|
var attach = $('#attach' + id + '> a').first(),
|
|
filename = attach.attr('title');
|
|
|
|
if (!filename) {
|
|
attach = attach.clone();
|
|
$('.attachment-size', attach).remove();
|
|
filename = $.trim(attach.text());
|
|
}
|
|
|
|
form.show();
|
|
dialog.addClass('saveas');
|
|
input.val(filename);
|
|
}
|
|
// attachment preview page
|
|
else if (rcmail.env.action == 'get') {
|
|
id = rcmail.env.part;
|
|
form.show();
|
|
dialog.addClass('saveas');
|
|
input.val(rcmail.env.filename);
|
|
}
|
|
else {
|
|
form.hide();
|
|
dialog.removeClass('saveas');
|
|
label = 'saveall';
|
|
}
|
|
|
|
$('#foldercreatelink').attr('tabindex', 0);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
if (!file_api.env.folder)
|
|
return;
|
|
|
|
var lock = rcmail.set_busy(true, 'saving'),
|
|
request = {
|
|
act: 'save-file',
|
|
source: rcmail.env.mailbox,
|
|
uid: rcmail.env.uid,
|
|
dest: file_api.env.folder
|
|
};
|
|
|
|
if (id) {
|
|
request.id = id;
|
|
request.name = input.val();
|
|
}
|
|
|
|
rcmail.http_post('plugin.kolab_files', request, lock);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
if (!rcmail.env.folders_loaded) {
|
|
fn = function() {
|
|
rcmail.env.folder_list_selector = '#files-dialog #files-folder-list';
|
|
rcmail.env.folder_search_selector = '#files-dialog #foldersearch';
|
|
file_api.folder_list();
|
|
rcmail.env.folders_loaded = true;
|
|
};
|
|
}
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.' + label),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction'],
|
|
minWidth: 250,
|
|
minHeight: 300,
|
|
height: 400,
|
|
width: 300
|
|
}, fn);
|
|
|
|
// "enable" folder creation when dialog is displayed in parent window
|
|
if (rcmail.is_framed()) {
|
|
parent.rcmail.enable_command('folder-create', true);
|
|
parent.rcmail.folder_create = function() {
|
|
win.kolab_files_folder_create_dialog();
|
|
};
|
|
}
|
|
};
|
|
|
|
// file selection dialog
|
|
function kolab_files_selector_dialog()
|
|
{
|
|
var dialog = $('#files-compose-dialog'), buttons = {};
|
|
|
|
buttons[rcmail.gettext('kolab_files.attachsel')] = function () {
|
|
var list = [];
|
|
$('#filelist tr.selected').each(function() {
|
|
list.push($(this).data('file'));
|
|
});
|
|
|
|
kolab_dialog_close(this);
|
|
|
|
if (list.length) {
|
|
// display upload indicator and cancel button
|
|
var content = '<span>' + rcmail.get_label('kolab_files.attaching') + '</span>',
|
|
id = new Date().getTime();
|
|
|
|
rcmail.add2attachment_list(id, {name:'', html:content, classname:'uploading', complete:false});
|
|
|
|
// send request
|
|
rcmail.http_post('plugin.kolab_files', {
|
|
act: 'attach-file',
|
|
files: list,
|
|
id: rcmail.env.compose_id,
|
|
uploadid: id
|
|
});
|
|
}
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.selectfiles'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction'],
|
|
minWidth: 500,
|
|
minHeight: 300,
|
|
width: 700,
|
|
height: 500
|
|
}, function() { rcmail.file_list.resize(); });
|
|
|
|
if (!rcmail.env.files_loaded) {
|
|
rcmail.env.folder_list_selector = '#files-compose-dialog #files-folder-list';
|
|
rcmail.env.folder_search_selector = '#files-compose-dialog #foldersearch';
|
|
file_api.folder_list();
|
|
rcmail.env.files_loaded = true;
|
|
}
|
|
else {
|
|
rcmail.file_list.clear_selection();
|
|
}
|
|
};
|
|
|
|
function kolab_files_attach_menu_open(p)
|
|
{
|
|
if (!p || !p.props || p.props.menu != 'attachmentmenu')
|
|
return;
|
|
|
|
var id = p.props.id;
|
|
|
|
$('#attachmenusaveas').unbind('click').attr('onclick', '').click(function(e) {
|
|
return kolab_directory_selector_dialog(id);
|
|
});
|
|
};
|
|
|
|
// folder creation dialog
|
|
function kolab_files_folder_create_dialog()
|
|
{
|
|
var dialog = $('#files-folder-create-dialog'),
|
|
buttons = {},
|
|
select = $('select[name="parent"]', dialog).html(''),
|
|
input = $('input[name="name"]', dialog).val('');
|
|
|
|
buttons[rcmail.gettext('kolab_files.create')] = function () {
|
|
var folder = '', name = input.val(), parent = select.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
if (parent)
|
|
folder = parent + file_api.env.directory_separator;
|
|
|
|
folder += name;
|
|
|
|
file_api.folder_create(folder);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.foldercreate'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction']
|
|
});
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// build parent selector
|
|
select.append($('<option>').val('').text('---'));
|
|
$.each(file_api.env.folders, function(i, f) {
|
|
var n, option = $('<option>'), name = escapeHTML(f.name);
|
|
|
|
for (n=0; n<f.depth; n++)
|
|
name = ' ' + name;
|
|
|
|
option.val(i).html(name).appendTo(select);
|
|
|
|
if (i == file_api.env.folder)
|
|
option.attr('selected', true);
|
|
});
|
|
};
|
|
|
|
// folder edit dialog
|
|
function kolab_files_folder_edit_dialog()
|
|
{
|
|
var dialog = $('#files-folder-edit-dialog'),
|
|
buttons = {}, options = [],
|
|
separator = file_api.env.directory_separator,
|
|
arr = file_api.env.folder.split(separator),
|
|
folder = arr.pop(),
|
|
path = arr.join(separator),
|
|
select = $('select[name="parent"]', dialog).html(''),
|
|
input = $('input[name="name"]', dialog).val(folder);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
var folder = '', name = input.val(), parent = select.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
if (parent)
|
|
folder = parent + separator;
|
|
|
|
folder += name;
|
|
|
|
file_api.folder_rename(file_api.env.folder, folder);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.folderedit'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction']
|
|
});
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// build parent selector
|
|
options.push($('<option>').val('').text('---'));
|
|
$.each(file_api.env.folders, function(i, f) {
|
|
var n, name = escapeHTML(f.name);
|
|
|
|
for (n=0; n<f.depth; n++)
|
|
name = ' ' + name;
|
|
|
|
options.push($('<option>').val(i).html(name));
|
|
});
|
|
|
|
select.append(options).val(path);
|
|
};
|
|
|
|
// folder mounting dialog
|
|
function kolab_files_folder_mount_dialog()
|
|
{
|
|
var args = {buttons: {}, title: rcmail.gettext('kolab_files.foldermount')},
|
|
dialog = $('#files-folder-mount-dialog'),
|
|
input = $('#folder-mount-name').val('');
|
|
|
|
args.buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
var args = {}, folder = input.val(),
|
|
driver = $('input[name="driver"]:checked', dialog).val();
|
|
|
|
if (!folder || !driver)
|
|
return;
|
|
|
|
args.folder = folder;
|
|
args.driver = driver;
|
|
|
|
$('#source-' + driver + ' input').each(function() {
|
|
if (this.name.startsWith(driver + '[')) {
|
|
args[this.name.substring(driver.length + 1, this.name.length - 1)] = this.value;
|
|
}
|
|
});
|
|
|
|
$('.auth-options input', dialog).each(function() {
|
|
args[this.name] = this.type == 'checkbox' && !this.checked ? '' : this.value;
|
|
});
|
|
|
|
file_api.folder_mount(args);
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
args.buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// close folderoption menu
|
|
rcmail.hide_menu('folderoptions');
|
|
|
|
// initialize drivers list
|
|
if (!rcmail.drivers_list_initialized) {
|
|
rcmail.drivers_list_initialized = true;
|
|
|
|
$('td.source', dialog).each(function() {
|
|
$(this).click(function() {
|
|
$('td.selected', dialog).removeClass('selected');
|
|
dialog.find('.driverform').hide();
|
|
$(this).addClass('selected').find('.driverform').show();
|
|
$('input[type="radio"]', this).prop('checked', true);
|
|
});
|
|
});
|
|
}
|
|
|
|
args.button_classes = ['mainaction'];
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, args, function() {
|
|
$('td.source:first', dialog).click();
|
|
input.focus();
|
|
});
|
|
};
|
|
|
|
// file edition dialog
|
|
function kolab_files_file_edit_dialog(file)
|
|
{
|
|
var dialog = $('#files-file-edit-dialog'),
|
|
buttons = {}, name = file_api.file_name(file)
|
|
input = $('input[name="name"]', dialog).val(name);
|
|
|
|
buttons[rcmail.gettext('kolab_files.save')] = function () {
|
|
var folder = file_api.file_path(file), name = input.val();
|
|
|
|
if (!name)
|
|
return;
|
|
|
|
name = folder + file_api.env.directory_separator + name;
|
|
|
|
// @TODO: now we only update filename
|
|
if (name != file)
|
|
file_api.file_rename(file, name);
|
|
kolab_dialog_close(this);
|
|
};
|
|
buttons[rcmail.gettext('kolab_files.cancel')] = function () {
|
|
kolab_dialog_close(this);
|
|
};
|
|
|
|
// Fix submitting form with Enter
|
|
$('form', dialog).submit(kolab_dialog_submit_handler);
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, {
|
|
title: rcmail.gettext('kolab_files.fileedit'),
|
|
buttons: buttons,
|
|
button_classes: ['mainaction']
|
|
});
|
|
};
|
|
|
|
function kolab_dialog_show(content, params, onopen)
|
|
{
|
|
params = $.extend({
|
|
modal: true,
|
|
resizable: true,
|
|
closeOnEscape: (!bw.ie6 && !bw.ie7), // disabled for performance reasons
|
|
minWidth: 400,
|
|
minHeight: 300,
|
|
width: 500,
|
|
height: 400
|
|
}, params || {});
|
|
|
|
// dialog close handler
|
|
params.close = function(e, ui) {
|
|
var elem, stack = rcmail.dialog_stack;
|
|
|
|
content.appendTo(document.body).hide();
|
|
$(this).parent().remove(); // remove dialog
|
|
|
|
// focus previously focused element (guessed)
|
|
stack.pop();
|
|
if (stack.length) {
|
|
elem = stack[stack.length-1].find('input[type!="hidden"]:not(:hidden):first');
|
|
if (!elem.length)
|
|
elem = stack[stack.length-1].parent().find('a[role="button"], .ui-dialog-buttonpane button').first();
|
|
}
|
|
|
|
(elem && elem.length ? elem : window).focus();
|
|
};
|
|
|
|
// display it as popup
|
|
var dialog = rcmail.show_popup_dialog('', params.title, params.buttons, params);
|
|
|
|
content.appendTo(dialog).show().find('input[type!="hidden"]:not(:hidden):first').focus();
|
|
|
|
if (onopen) onopen(content);
|
|
|
|
// save dialog reference, to handle focus when closing one of opened dialogs
|
|
if (!rcmail.dialog_stack)
|
|
rcmail.dialog_stack = [];
|
|
|
|
rcmail.dialog_stack.push(dialog);
|
|
};
|
|
|
|
// Handle form submit with Enter key, click first dialog button instead
|
|
function kolab_dialog_submit_handler()
|
|
{
|
|
$(this).parents('.ui-dialog').find('.ui-button').first().click();
|
|
return false;
|
|
};
|
|
|
|
// Hides dialog
|
|
function kolab_dialog_close(dialog)
|
|
{
|
|
(rcmail.is_framed() ? window.parent : window).$(dialog).dialog('close');
|
|
};
|
|
|
|
// smart upload button
|
|
function kolab_files_upload_input(button)
|
|
{
|
|
var link = $(button),
|
|
file = $('<input>'),
|
|
offset = link.offset();
|
|
|
|
function move_file_input(e) {
|
|
file.css({top: (e.pageY - offset.top - 10) + 'px', left: (e.pageX - offset.left - 10) + 'px'});
|
|
}
|
|
|
|
file.attr({name: 'file[]', type: 'file', multiple: 'multiple', size: 5, title: link.attr('title'), tabindex: "-1"})
|
|
.change(function() { rcmail.files_upload('#filesuploadform'); })
|
|
.click(function() { setTimeout(function() { link.mouseleave(); }, 20); })
|
|
// opacity:0 does the trick, display/visibility doesn't work
|
|
.css({opacity: 0, cursor: 'pointer', outline: 'none', position: 'absolute'});
|
|
|
|
// In FF and IE we need to move the browser file-input's button under the cursor
|
|
// Thanks to the size attribute above we know the length of the input field
|
|
if (bw.mz || bw.ie)
|
|
file.css({marginLeft: '-80px'});
|
|
|
|
// Note: now, I observe problem with cursor style on FF < 4 only
|
|
// Need position: relative (Bug #2615)
|
|
link.css({overflow: 'hidden', cursor: 'pointer', position: 'relative'})
|
|
.mouseenter(function() { this.__active = true; })
|
|
// place button under the cursor
|
|
.mousemove(function(e) {
|
|
if (rcmail.commands['files-upload'] && this.__active)
|
|
move_file_input(e);
|
|
// move the input away if button is disabled
|
|
else
|
|
$(this).mouseleave();
|
|
})
|
|
.mouseleave(function() {
|
|
file.css({top: '-10000px', left: '-10000px'});
|
|
this.__active = false;
|
|
})
|
|
.attr('onclick', '') // remove default button action
|
|
.click(function(e) {
|
|
// forward click if mouse-enter event was missed
|
|
if (rcmail.commands['files-upload'] && !this.__active) {
|
|
this.__active = true;
|
|
move_file_input(e);
|
|
file.trigger(e);
|
|
}
|
|
})
|
|
.mouseleave() // initially disable/hide input
|
|
.append(file);
|
|
};
|
|
|
|
|
|
/***********************************************************/
|
|
/********** Main functionality **********/
|
|
/***********************************************************/
|
|
|
|
// for reordering column array (Konqueror workaround)
|
|
// and for setting some message list global variables
|
|
kolab_files_list_coltypes = function()
|
|
{
|
|
var n, list = rcmail.file_list;
|
|
|
|
rcmail.env.subject_col = null;
|
|
|
|
if ((n = $.inArray('name', rcmail.env.file_coltypes)) >= 0) {
|
|
rcmail.env.subject_col = n;
|
|
list.subject_col = n;
|
|
}
|
|
|
|
list.init_header();
|
|
};
|
|
|
|
kolab_files_set_list_options = function(cols, sort_col, sort_order)
|
|
{
|
|
var update = 0, i, idx, name, newcols = [], oldcols = rcmail.env.file_coltypes;
|
|
|
|
if (sort_col === undefined)
|
|
sort_col = rcmail.env.sort_col;
|
|
if (!sort_order)
|
|
sort_order = rcmail.env.sort_order;
|
|
|
|
if (rcmail.env.sort_col != sort_col || rcmail.env.sort_order != sort_order) {
|
|
update = 1;
|
|
rcmail.set_list_sorting(sort_col, sort_order);
|
|
}
|
|
|
|
if (cols && cols.length) {
|
|
// make sure new columns are added at the end of the list
|
|
for (i=0; i<oldcols.length; i++) {
|
|
name = oldcols[i];
|
|
idx = $.inArray(name, cols);
|
|
if (idx != -1) {
|
|
newcols.push(name);
|
|
delete cols[idx];
|
|
}
|
|
}
|
|
for (i=0; i<cols.length; i++)
|
|
if (cols[i])
|
|
newcols.push(cols[i]);
|
|
|
|
if (newcols.join() != oldcols.join()) {
|
|
update += 2;
|
|
oldcols = newcols;
|
|
}
|
|
}
|
|
|
|
if (update == 1)
|
|
rcmail.command('files-list', {sort: sort_col, reverse: sort_order == 'DESC'});
|
|
else if (update) {
|
|
rcmail.http_post('files/prefs', {
|
|
kolab_files_list_cols: oldcols,
|
|
kolab_files_sort_col: sort_col,
|
|
kolab_files_sort_order: sort_order
|
|
}, rcmail.set_busy(true, 'loading'));
|
|
}
|
|
};
|
|
|
|
kolab_files_set_coltypes = function(list)
|
|
{
|
|
var i, found, name, cols = list.list.tHead.rows[0].cells;
|
|
|
|
rcmail.env.file_coltypes = [];
|
|
|
|
for (i=0; i<cols.length; i++)
|
|
if (cols[i].id && cols[i].id.match(/^rcm/)) {
|
|
name = cols[i].id.replace(/^rcm/, '');
|
|
rcmail.env.file_coltypes.push(name);
|
|
}
|
|
|
|
// if ((found = $.inArray('name', rcmail.env.file_coltypes)) >= 0)
|
|
// rcmail.env.subject_col = found;
|
|
rcmail.env.subject_col = list.subject_col;
|
|
|
|
rcmail.http_post('files/prefs', {kolab_files_list_cols: rcmail.env.file_coltypes});
|
|
};
|
|
|
|
kolab_files_list_dblclick = function(list)
|
|
{
|
|
rcmail.command('files-open');
|
|
};
|
|
|
|
kolab_files_list_select = function(list)
|
|
{
|
|
var selected = list.selection.length;
|
|
|
|
rcmail.enable_command(rcmail.env.file_commands_all, selected);
|
|
rcmail.enable_command(rcmail.env.file_commands, selected == 1);
|
|
|
|
// reset all-pages-selection
|
|
// if (list.selection.length && list.selection.length != list.rowcount)
|
|
// rcmail.select_all_mode = false;
|
|
|
|
// enable files-
|
|
if (selected == 1) {
|
|
// get file mimetype
|
|
var type = $('tr.selected', list.list).data('type');
|
|
rcmail.env.viewer = file_api.file_type_supported(type);
|
|
}
|
|
else
|
|
rcmail.env.viewer = 0;
|
|
/*
|
|
) {
|
|
// caps = this.browser_capabilities().join();
|
|
href = '?' + $.param({_task: 'files', _action: 'open', file: file, viewer: viewer == 2 ? 1 : 0});
|
|
var win = window.open(href, rcmail.html_identifier('rcubefile'+file));
|
|
if (win)
|
|
setTimeout(function() { win.focus(); }, 10);
|
|
}
|
|
*/
|
|
rcmail.enable_command('files-open', rcmail.env.viewer);
|
|
};
|
|
|
|
kolab_files_list_keypress = function(list)
|
|
{
|
|
if (list.modkey == CONTROL_KEY)
|
|
return;
|
|
|
|
if (list.key_pressed == list.ENTER_KEY)
|
|
rcmail.command('files-open');
|
|
else if (list.key_pressed == list.DELETE_KEY || list.key_pressed == list.BACKSPACE_KEY)
|
|
rcmail.command('files-delete');
|
|
};
|
|
|
|
kolab_files_drag_start = function(e)
|
|
{
|
|
rcmail.env.drag_target = null;
|
|
|
|
if (rcmail.folder_list)
|
|
rcmail.folder_list.drag_start();
|
|
};
|
|
|
|
kolab_files_drag_end = function(e)
|
|
{
|
|
if (rcmail.folder_list) {
|
|
rcmail.folder_list.drag_end();
|
|
|
|
if (rcmail.env.drag_target) {
|
|
var modkey = rcube_event.get_modifier(e),
|
|
menu = rcmail.gui_objects.file_dragmenu;
|
|
|
|
rcmail.file_list.draglayer.hide();
|
|
|
|
if (menu && modkey == SHIFT_KEY && rcmail.commands['files-copy']) {
|
|
var pos = rcube_event.get_mouse_pos(e);
|
|
$(menu).css({top: (pos.y-10)+'px', left: (pos.x-10)+'px'}).show();
|
|
return;
|
|
}
|
|
|
|
rcmail.command('files-move', rcmail.env.drag_target);
|
|
}
|
|
}
|
|
};
|
|
|
|
kolab_files_drag_move = function(e)
|
|
{
|
|
if (rcmail.folder_list) {
|
|
var mouse = rcube_event.get_mouse_pos(e);
|
|
|
|
rcmail.env.drag_target = rcmail.folder_list.intersects(mouse, true);
|
|
}
|
|
};
|
|
|
|
kolab_files_drag_menu_action = function(command)
|
|
{
|
|
var menu = rcmail.gui_objects.file_dragmenu;
|
|
|
|
if (menu)
|
|
$(menu).hide();
|
|
|
|
rcmail.command(command, rcmail.env.drag_target);
|
|
};
|
|
|
|
kolab_files_selected = function()
|
|
{
|
|
var files = [];
|
|
$.each(rcmail.file_list.get_selection(), function(i, v) {
|
|
var name, row = $('#rcmrow'+v);
|
|
|
|
if (row.length == 1 && (name = row.data('file')))
|
|
files.push(name);
|
|
});
|
|
|
|
return files;
|
|
};
|
|
|
|
kolab_files_frame_load = function(frame)
|
|
{
|
|
var win = frame.contentWindow;
|
|
|
|
rcmail.file_editor = win.file_editor && win.file_editor.editable ? win.file_editor : null;
|
|
|
|
if (rcmail.file_editor)
|
|
rcmail.enable_command('files-edit', true);
|
|
|
|
rcmail.enable_command('files-print', (rcmail.file_editor && rcmail.file_editor.printable) ||
|
|
(rcmail.env.file_data && /^image\//i.test(rcmail.env.file_data.type)));
|
|
|
|
// detect Print button and check if it can be accessed
|
|
try {
|
|
if ($('#fileframe').contents().find('#print').length)
|
|
rcmail.enable_command('files-print', true);
|
|
}
|
|
catch(e) {};
|
|
};
|
|
|
|
// activate html5 file drop feature (if browser supports it)
|
|
kolab_files_drag_drop_init = function(container)
|
|
{
|
|
if (!window.FormData && !(window.XMLHttpRequest && XMLHttpRequest.prototype && XMLHttpRequest.prototype.sendAsBinary)) {
|
|
return;
|
|
}
|
|
|
|
if (!container.length)
|
|
return;
|
|
|
|
$(document.body).bind('dragover dragleave drop', function(e) {
|
|
if (!file_api.env.folder)
|
|
return;
|
|
|
|
e.preventDefault();
|
|
container[e.type == 'dragover' ? 'addClass' : 'removeClass']('active');
|
|
});
|
|
|
|
container.bind('dragover dragleave', function(e) {
|
|
return kolab_files_drag_hover(e);
|
|
})
|
|
container.children('div').bind('dragover dragleave', function(e) {
|
|
return kolab_files_drag_hover(e);
|
|
})
|
|
container.get(0).addEventListener('drop', function(e) {
|
|
// abort event and reset UI
|
|
kolab_files_drag_hover(e);
|
|
return file_api.file_drop(e);
|
|
}, false);
|
|
};
|
|
|
|
// handler for drag/drop on element
|
|
kolab_files_drag_hover = function(e)
|
|
{
|
|
if (!file_api.env.folder)
|
|
return;
|
|
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
|
|
var elem = $(e.target);
|
|
|
|
if (!elem.hasClass('droptarget'))
|
|
elem = elem.parents('.droptarget');
|
|
|
|
elem[e.type == 'dragover' ? 'addClass' : 'removeClass']('hover');
|
|
};
|
|
|
|
// returns localized file size
|
|
kolab_files_file_size = function(size)
|
|
{
|
|
var i, units = ['GB', 'MB', 'KB', 'B'];
|
|
|
|
size = file_api.file_size(size);
|
|
|
|
for (i = 0; i < units.length; i++)
|
|
if (size.toUpperCase().indexOf(units[i]) > 0)
|
|
return size.replace(units[i], rcmail.gettext(units[i]));
|
|
|
|
return size;
|
|
};
|
|
|
|
kolab_files_progress_str = function(param)
|
|
{
|
|
var current, total = file_api.file_size(param.total).toUpperCase();
|
|
|
|
if (total.indexOf('GB') > 0)
|
|
current = parseFloat(param.current/1073741824).toFixed(1);
|
|
else if (total.indexOf('MB') > 0)
|
|
current = parseFloat(param.current/1048576).toFixed(1);
|
|
else if (total.indexOf('KB') > 0)
|
|
current = parseInt(param.current/1024);
|
|
else
|
|
current = param.current;
|
|
|
|
total = kolab_files_file_size(param.total);
|
|
|
|
return rcmail.gettext('uploadprogress')
|
|
.replace(/\$percent/, param.percent + '%')
|
|
.replace(/\$current/, current)
|
|
.replace(/\$total/, total);
|
|
};
|
|
|
|
|
|
/***********************************************************/
|
|
/********** Commands **********/
|
|
/***********************************************************/
|
|
|
|
rcube_webmail.prototype.files_sort = function(props)
|
|
{
|
|
var params = {},
|
|
sort_order = this.env.sort_order,
|
|
sort_col = !this.env.disabled_sort_col ? props : this.env.sort_col;
|
|
|
|
if (!this.env.disabled_sort_order)
|
|
sort_order = this.env.sort_col == sort_col && sort_order == 'ASC' ? 'DESC' : 'ASC';
|
|
|
|
// set table header and update env
|
|
this.set_list_sorting(sort_col, sort_order);
|
|
|
|
this.http_post('files/prefs', {kolab_files_sort_col: sort_col, kolab_files_sort_order: sort_order});
|
|
|
|
params.sort = sort_col;
|
|
params.reverse = sort_order == 'DESC';
|
|
|
|
this.command('files-list', params);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_search = function()
|
|
{
|
|
var value = $(this.gui_objects.filesearchbox).val();
|
|
|
|
if (value)
|
|
file_api.file_search(value, $('#search_all_folders').is(':checked'));
|
|
else
|
|
file_api.file_search_reset();
|
|
};
|
|
|
|
rcube_webmail.prototype.files_search_reset = function()
|
|
{
|
|
$(this.gui_objects.filesearchbox).val('');
|
|
|
|
file_api.file_search_reset();
|
|
};
|
|
|
|
rcube_webmail.prototype.files_folder_delete = function()
|
|
{
|
|
if (confirm(this.get_label('kolab_files.folderdeleteconfirm')))
|
|
file_api.folder_delete(file_api.env.folder);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_delete = function()
|
|
{
|
|
if (!confirm(this.get_label('kolab_files.filedeleteconfirm')))
|
|
return;
|
|
|
|
var files = this.env.file ? [this.env.file] : kolab_files_selected();
|
|
file_api.file_delete(files);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_move = function(folder)
|
|
{
|
|
var files = kolab_files_selected();
|
|
file_api.file_move(files, folder);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_copy = function(folder)
|
|
{
|
|
var files = kolab_files_selected();
|
|
file_api.file_copy(files, folder);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_upload = function(form)
|
|
{
|
|
if (form)
|
|
file_api.file_upload(form);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_list = function(param)
|
|
{
|
|
// just rcmail wrapper, to handle command busy states
|
|
file_api.file_list(param);
|
|
}
|
|
|
|
rcube_webmail.prototype.files_list_update = function(head)
|
|
{
|
|
var list = this.file_list;
|
|
|
|
list.clear();
|
|
$('thead', list.fixed_header ? list.fixed_header : list.list).html(head);
|
|
kolab_files_list_coltypes();
|
|
file_api.file_list();
|
|
};
|
|
|
|
rcube_webmail.prototype.files_get = function()
|
|
{
|
|
var files = this.env.file ? [this.env.file] : kolab_files_selected();
|
|
|
|
if (files.length == 1)
|
|
file_api.file_get(files[0], {'force-download': true});
|
|
};
|
|
|
|
rcube_webmail.prototype.files_open = function()
|
|
{
|
|
var files = kolab_files_selected();
|
|
|
|
if (files.length == 1)
|
|
file_api.file_open(files[0], rcmail.env.viewer);
|
|
};
|
|
|
|
// enable file editor
|
|
rcube_webmail.prototype.files_edit = function()
|
|
{
|
|
if (this.file_editor) {
|
|
this.file_editor.enable();
|
|
this.enable_command('files-save', true);
|
|
}
|
|
};
|
|
|
|
rcube_webmail.prototype.files_save = function()
|
|
{
|
|
if (!this.file_editor)
|
|
return;
|
|
|
|
// binary files like ODF need to be updated using FormData
|
|
if (this.file_editor.getContentCallback) {
|
|
if (!file_api.file_uploader_support())
|
|
return;
|
|
|
|
file_api.req = file_api.set_busy(true, 'saving');
|
|
// this.file_editor.disable();
|
|
this.file_editor.getContentCallback(function(content, filename) {
|
|
file_api.file_uploader([content], {
|
|
action: 'file_update',
|
|
params: {file: rcmail.env.file, info: 1, token: file_api.env.token},
|
|
response_handler: 'file_save_response',
|
|
fieldname: 'content',
|
|
single: true
|
|
});
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
var content = this.file_editor.getContent();
|
|
|
|
file_api.file_save(this.env.file, content);
|
|
};
|
|
|
|
rcube_webmail.prototype.files_print = function()
|
|
{
|
|
if (this.file_editor && this.file_editor.printable)
|
|
this.file_editor.print();
|
|
else if (/^image\//i.test(this.env.file_data.type)) {
|
|
var frame = $('#fileframe').get(0),
|
|
win = frame ? frame.contentWindow : null;
|
|
|
|
if (win) {
|
|
win.focus();
|
|
win.print();
|
|
}
|
|
}
|
|
else {
|
|
// e.g. Print button in PDF viewer
|
|
try {
|
|
$('#fileframe').contents().find('#print').click();
|
|
}
|
|
catch(e) {};
|
|
}
|
|
};
|
|
|
|
rcube_webmail.prototype.files_set_quota = function(p)
|
|
{
|
|
if (p.total && window.file_api) {
|
|
p.used *= 1024;
|
|
p.total *= 1024;
|
|
p.title = file_api.file_size(p.used) + ' / ' + file_api.file_size(p.total)
|
|
+ ' (' + p.percent + '%)';
|
|
}
|
|
|
|
p.type = this.env.quota_type;
|
|
|
|
this.set_quota(p);
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_create = function()
|
|
{
|
|
kolab_files_folder_create_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_rename = function()
|
|
{
|
|
kolab_files_folder_edit_dialog();
|
|
};
|
|
|
|
rcube_webmail.prototype.folder_mount = function()
|
|
{
|
|
kolab_files_folder_mount_dialog();
|
|
};
|
|
|
|
|
|
/**********************************************************/
|
|
/********* Files API handler **********/
|
|
/**********************************************************/
|
|
|
|
function kolab_files_ui()
|
|
{
|
|
this.requests = {};
|
|
this.uploads = [];
|
|
|
|
/*
|
|
// Called on "session expired" session
|
|
this.logout = function(response) {};
|
|
|
|
// called when a request timed out
|
|
this.request_timed_out = function() {};
|
|
|
|
// called on start of the request
|
|
this.set_request_time = function() {};
|
|
|
|
// called on request response
|
|
this.update_request_time = function() {};
|
|
*/
|
|
// set state
|
|
this.set_busy = function(a, message)
|
|
{
|
|
if (this.req)
|
|
rcmail.hide_message(this.req);
|
|
|
|
return rcmail.set_busy(a, message);
|
|
};
|
|
|
|
// displays error message
|
|
this.display_message = function(label, type)
|
|
{
|
|
return rcmail.display_message(this.t(label), type);
|
|
};
|
|
|
|
this.http_error = function(request, status, err)
|
|
{
|
|
rcmail.http_error(request, status, err);
|
|
};
|
|
|
|
// folders list request
|
|
this.folder_list = function()
|
|
{
|
|
this.req = this.set_busy(true, 'loading');
|
|
this.request('folder_list', {}, 'folder_list_response');
|
|
};
|
|
|
|
// folder list response handler
|
|
this.folder_list_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var first, body, rows = [],
|
|
list_selector = rcmail.env.folder_list_selector || '#files-folder-list',
|
|
search_selector = rcmail.env.folder_search_selector || '#foldersearch',
|
|
elem = $(list_selector),
|
|
searchbox = $(search_selector),
|
|
list = $('<ul class="treelist listing folderlist"></ul>'),
|
|
collections = ['audio', 'video', 'image', 'document'];
|
|
|
|
// try parent window if the list element does not exist
|
|
// i.e. called from dialog in parent window
|
|
if (!elem.length && window.parent && parent.rcmail) {
|
|
body = window.parent.document.body;
|
|
elem = $(list_selector, body);
|
|
searchbox = $(search_selector, body);
|
|
}
|
|
|
|
if (elem.data('no-collections') == true)
|
|
collections = [];
|
|
|
|
elem.html('');
|
|
|
|
this.env.folders = this.folder_list_parse(response.result && response.result.list ? response.result.list : response.result);
|
|
|
|
$.each(this.env.folders, function(i, f) {
|
|
var row;
|
|
if (row = file_api.folder_list_row(i, f)) {
|
|
if (!first)
|
|
first = i;
|
|
rows.push(row);
|
|
}
|
|
});
|
|
|
|
// add virtual collections
|
|
$.each(collections, function(i, n) {
|
|
var row = $('<li class="mailbox collection ' + n + '"></li>');
|
|
|
|
row.attr('id', 'rcmli' + rcmail.html_identifier_encode('folder-collection-' + n))
|
|
.append($('<a class="name"></a>').text(rcmail.gettext('kolab_files.collection_' + n)))
|
|
|
|
rows.push(row);
|
|
});
|
|
|
|
list.append(rows).appendTo(elem)
|
|
.on('click', 'a.subscription', function(e) {
|
|
return file_api.folder_list_subscription_button_click(this);
|
|
});
|
|
|
|
if (rcmail.folder_list) {
|
|
rcmail.folder_list.reset();
|
|
this.search_results_widget = null;
|
|
}
|
|
|
|
// init treelist widget
|
|
rcmail.folder_list = new rcube_treelist_widget(list, {
|
|
selectable: true,
|
|
id_prefix: 'rcmli',
|
|
parent_focus: true,
|
|
searchbox: searchbox,
|
|
id_encode: rcmail.html_identifier_encode,
|
|
id_decode: rcmail.html_identifier_decode,
|
|
check_droptarget: function(node) {
|
|
return !node.virtual
|
|
&& node.id != file_api.env.folder
|
|
&& $.inArray('collection', node.classes) == -1;
|
|
}
|
|
});
|
|
|
|
rcmail.folder_list
|
|
.addEventListener('collapse', function(node) { file_api.folder_collapsed(node); })
|
|
.addEventListener('expand', function(node) { file_api.folder_collapsed(node); })
|
|
.addEventListener('beforeselect', function(node) { return !rcmail.busy; })
|
|
.addEventListener('search', function(search) { file_api.folder_search(search); })
|
|
.addEventListener('select', function(node) {
|
|
if (file_api.search_results_widget)
|
|
file_api.search_results_widget.select();
|
|
file_api.folder_select(node.id);
|
|
});
|
|
|
|
// select first folder?
|
|
if (response.result.auth_errors) { }
|
|
else if (this.env.folder)
|
|
rcmail.folder_list.select(this.env.folder);
|
|
else if (this.env.collection)
|
|
rcmail.folder_list.select('folder-collection-' + this.env.collection);
|
|
else if (first)
|
|
rcmail.folder_list.select(first);
|
|
|
|
// add tree icons
|
|
// this.folder_list_tree(this.env.folders);
|
|
|
|
// handle authentication errors on external sources
|
|
this.folder_list_auth_errors(response.result);
|
|
};
|
|
|
|
this.folder_select = function(folder)
|
|
{
|
|
if (rcmail.busy)
|
|
return;
|
|
|
|
var is_collection = folder.match(/^folder-collection-(.*)$/),
|
|
collection = RegExp.$1 || null;
|
|
|
|
if (is_collection)
|
|
folder = null;
|
|
|
|
// search-reset can re-select the same folder, skip
|
|
if (this.env.folder == folder && this.env.collection == collection)
|
|
return;
|
|
|
|
this.env.folder = folder;
|
|
this.env.collection = collection;
|
|
|
|
rcmail.enable_command('files-list', true);
|
|
rcmail.enable_command('files-folder-delete', 'folder-rename', 'files-upload', !is_collection);
|
|
rcmail.command('files-list', is_collection ? {collection: collection} : {folder: folder});
|
|
|
|
this.quota();
|
|
};
|
|
|
|
this.folder_unselect = function()
|
|
{
|
|
rcmail.folder_list.select();
|
|
this.env.folder = null;
|
|
this.env.collection = null;
|
|
rcmail.enable_command('files-folder-delete', 'files-upload', false);
|
|
};
|
|
|
|
this.folder_collapsed = function(node)
|
|
{
|
|
var prefname = 'kolab_files_collapsed_folders',
|
|
old = rcmail.env[prefname],
|
|
entry = '&' + urlencode(node.id) + '&';
|
|
|
|
if (node.collapsed) {
|
|
rcmail.env[prefname] = rcmail.env[prefname] + entry;
|
|
|
|
// select the folder if one of its childs is currently selected
|
|
// don't select if it's virtual (#1488346)
|
|
if (!node.virtual && this.env.folder && this.env.folder.startsWith(node.id + '/')) {
|
|
rcmail.folder_list.select(node.id);
|
|
}
|
|
}
|
|
else {
|
|
rcmail.env[prefname] = rcmail.env[prefname].replace(entry, '');
|
|
}
|
|
|
|
if (old !== rcmail.env[prefname] && (!rcmail.file_list || !rcmail.file_list.drag_active))
|
|
rcmail.command('save-pref', {name: prefname, value: rcmail.env[prefname]});
|
|
};
|
|
|
|
this.folder_list_row = function(i, folder, parent)
|
|
{
|
|
var toggle, sublist, collapsed, parent, parent_name,
|
|
row = $('<li class="mailbox"></li>'),
|
|
id = 'rcmli' + rcmail.html_identifier_encode(i);
|
|
|
|
row.attr('id', id).append($('<a>').text(folder.name));
|
|
|
|
if (folder.virtual)
|
|
row.addClass('virtual');
|
|
else if (folder.subscribed !== undefined)
|
|
row.append(this.folder_list_subscription_button(folder.subscribed));
|
|
|
|
folder.ref = row;
|
|
|
|
if (folder.depth) {
|
|
// find parent folder
|
|
parent_name = i.replace(/\/[^/]+$/, '');
|
|
if (!parent)
|
|
parent = $(this.env.folders[parent_name].ref);
|
|
|
|
toggle = $('div.treetoggle', parent);
|
|
sublist = $('> ul', parent);
|
|
|
|
if (!toggle.length) {
|
|
collapsed = rcmail.env.kolab_files_collapsed_folders.indexOf('&' + urlencode(parent_name) + '&') > -1;
|
|
|
|
toggle = $('<div>').attr('class', 'treetoggle' + (collapsed ? ' collapsed' : ' expanded'))
|
|
.html(' ').appendTo(parent);
|
|
|
|
sublist = $('<ul>').attr({role: 'group'}).appendTo(parent);
|
|
if (collapsed)
|
|
sublist.hide();
|
|
}
|
|
|
|
sublist.append(row);
|
|
}
|
|
else {
|
|
return row;
|
|
}
|
|
};
|
|
|
|
// create subscription button element
|
|
this.folder_list_subscription_button = function(subscribed)
|
|
{
|
|
return $('<a>').attr({
|
|
title: rcmail.gettext('kolab_files.listpermanent'),
|
|
class: 'subscription' + (subscribed ? ' subscribed' : ''),
|
|
'aria-checked': subscribed,
|
|
role: 'checkbox'
|
|
});
|
|
};
|
|
|
|
// subscription button handler
|
|
this.folder_list_subscription_button_click = function(elem)
|
|
{
|
|
var folder = $(elem).parent('li').prop('id').replace(/^rcmli/, ''),
|
|
selected = $(elem).hasClass('subscribed');
|
|
|
|
folder = folder.replace(/--xsR$/, ''); // this might be a search result
|
|
folder = rcmail.html_identifier_decode(folder);
|
|
file_api['folder_' + (selected ? 'unsubscribe' : 'subscribe')](folder);
|
|
return false;
|
|
};
|
|
|
|
// sets subscription button status
|
|
this.folder_list_subscription_state = function(elem, status)
|
|
{
|
|
$(elem).children('a.subscription')
|
|
.prop('aria-checked', status)[status ? 'addClass' : 'removeClass']('subscribed');
|
|
};
|
|
|
|
// Folder searching handler (for unsubscribed folders)
|
|
this.folder_search = function(search)
|
|
{
|
|
// hide search results
|
|
if (this.search_results_widget) {
|
|
this.search_results_container.hide();
|
|
this.search_results_widget.reset();
|
|
}
|
|
this.search_results = {};
|
|
|
|
// send search request to the server
|
|
if (search.query && search.execute) {
|
|
// cancel previous search request
|
|
if (this.listsearch_request) {
|
|
this.listsearch_request.abort();
|
|
this.listsearch_request = null;
|
|
}
|
|
|
|
var params = {search: search.query, unsubscribed: 1};
|
|
|
|
this.req = this.set_busy(true, rcmail.gettext('searching'));
|
|
this.listsearch_request = this.request('folder_list', params, 'folder_search_response');
|
|
}
|
|
else if (!search.query) {
|
|
if (this.listsearch_request) {
|
|
this.listsearch_request.abort();
|
|
this.listsearch_request = null;
|
|
}
|
|
|
|
// any subscription changed, make sure the newly added records
|
|
// are listed before collections not after
|
|
if (this.folder_subscribe) {
|
|
var r, last, move = [], rows = $(rcmail.folder_list.container).children('li');
|
|
|
|
if (rows.length && !$(rows[rows.length-1]).hasClass('collection')) {
|
|
// collect all folders to move
|
|
while (rows.length--) {
|
|
r = $(rows[rows.length]);
|
|
if (r.hasClass('collection'))
|
|
last = r;
|
|
else if (last)
|
|
break;
|
|
else
|
|
move.push(r);
|
|
}
|
|
|
|
if (last)
|
|
$.each(move, function() {
|
|
this.remove();
|
|
last.before(this);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// folder search response handler
|
|
this.folder_search_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var folders = response.result && response.result.list ? response.result.list : response.result;
|
|
|
|
if (!folders.length)
|
|
return;
|
|
|
|
folders = this.folder_list_parse(folders, 10000, false);
|
|
|
|
if (!this.search_results_widget) {
|
|
var list = rcmail.folder_list.container,
|
|
title = rcmail.gettext('kolab_files.additionalfolders'),
|
|
list_id = list.attr('id') || '0';
|
|
|
|
this.search_results_container = $('<div class="searchresults"></div>')
|
|
.append($('<h2 class="boxtitle" id="st:' + list_id + '"></h2>').text(title))
|
|
.insertAfter(list);
|
|
|
|
this.search_results_widget = new rcube_treelist_widget('<ul>', {
|
|
id_prefix: 'rcmli',
|
|
id_encode: rcmail.html_identifier_encode,
|
|
id_decode: rcmail.html_identifier_decode,
|
|
selectable: true
|
|
});
|
|
|
|
this.search_results_widget
|
|
.addEventListener('beforeselect', function(node) { return !rcmail.busy; })
|
|
.addEventListener('select', function(node) {
|
|
rcmail.folder_list.select();
|
|
file_api.folder_select(node.id);
|
|
});
|
|
|
|
this.search_results_widget.container
|
|
// copy classes from main list
|
|
.addClass(list.attr('class')).attr('aria-labelledby', 'st:' + list_id)
|
|
.appendTo(this.search_results_container)
|
|
.on('click', 'a.subscription', function(e) {
|
|
return file_api.folder_list_subscription_button_click(this);
|
|
});
|
|
}
|
|
|
|
// add results to the list
|
|
$.each(folders, function(i, folder) {
|
|
var node, separator = file_api.env.directory_separator,
|
|
path = i.split(separator),
|
|
html = [$('<a>').text(folder.name)];
|
|
|
|
// add subscription button
|
|
if (!folder.virtual)
|
|
html.push(file_api.folder_list_subscription_button(false));
|
|
|
|
path.pop();
|
|
|
|
file_api.search_results_widget.insert({
|
|
id: i,
|
|
classes: ['mailbox'],
|
|
text: folder.name,
|
|
html: html,
|
|
collapsed: false,
|
|
virtual: folder.virtual
|
|
}, path.length ? path.join(separator) : null);
|
|
});
|
|
|
|
this.search_results = folders;
|
|
this.search_results_container.show();
|
|
};
|
|
|
|
// folder subscribe request
|
|
this.folder_subscribe = function(folder)
|
|
{
|
|
this.env.folder_subscribe = folder;
|
|
this.req = this.set_busy(true, 'foldersubscribing');
|
|
this.request('folder_subscribe', {folder: folder}, 'folder_subscribe_response');
|
|
}
|
|
|
|
// folder subscribe response handler
|
|
this.folder_subscribe_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('foldersubscribed', 'confirmation');
|
|
|
|
var item, node = rcmail.folder_list.get_item(this.env.folder_subscribe);
|
|
|
|
if (this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
item = this.search_results_widget.get_item(this.env.folder_subscribe);
|
|
this.folder_list_subscription_state(item, true);
|
|
if (item = $(item).attr('id'))
|
|
this.folder_list_subscription_state($('#' + item.replace(/--xsR$/, '')), true);
|
|
}
|
|
|
|
// search result, move from search to main list widget
|
|
if (!node && this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
var i, html, dir, folder, separator = this.env.directory_separator,
|
|
path = this.env.folder_subscribe.split(separator);
|
|
|
|
// add all folders in a path to the main list if needed
|
|
// including the subscribed folder
|
|
for (i=0; i<path.length; i++) {
|
|
dir = path.slice(0, i + 1).join(separator);
|
|
node = rcmail.folder_list.get_node(dir);
|
|
|
|
if (!node) {
|
|
node = this.search_results_widget.get_node(dir);
|
|
if (!node) {
|
|
// sanity check
|
|
return;
|
|
}
|
|
|
|
if (i == path.length - 1) {
|
|
item = this.search_results_widget.get_item(dir);
|
|
this.folder_list_subscription_state(item, true);
|
|
}
|
|
|
|
folder = this.search_results[dir];
|
|
html = [$('<a>').text(folder.name)];
|
|
if (!folder.virtual)
|
|
html.push(this.folder_list_subscription_button(true));
|
|
|
|
node.html = html;
|
|
delete node.children;
|
|
|
|
rcmail.folder_list.insert(node, i > 0 ? path.slice(0, i).join(separator) : null);
|
|
// we're in search result, so there will be two records,
|
|
// add subscription button to the visible one, it was not cloned
|
|
if (!folder.virtual) {
|
|
node = rcmail.folder_list.get_item(dir);
|
|
$(node).append(file_api.folder_list_subscription_button(true));
|
|
}
|
|
|
|
this.env.folders[dir] = folder;
|
|
}
|
|
}
|
|
|
|
// now remove them from the search widget
|
|
while (path.length) {
|
|
dir = path.join(separator);
|
|
node = this.search_results_widget.get_item(dir);
|
|
|
|
if ($('ul[role="group"] > li', node).length)
|
|
break;
|
|
|
|
this.search_results_widget.remove(dir);
|
|
|
|
path.pop();
|
|
}
|
|
|
|
node = null;
|
|
}
|
|
|
|
if (node)
|
|
this.folder_list_subscription_state(node, true);
|
|
|
|
this.env.folders[this.env.folder_subscribe].subscribed = true;
|
|
};
|
|
|
|
// folder unsubscribe request
|
|
this.folder_unsubscribe = function(folder)
|
|
{
|
|
this.env.folder_subscribe = folder;
|
|
this.req = this.set_busy(true, 'folderunsubscribing');
|
|
this.request('folder_unsubscribe', {folder: folder}, 'folder_unsubscribe_response');
|
|
}
|
|
|
|
// folder unsubscribe response handler
|
|
this.folder_unsubscribe_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('folderunsubscribed', 'confirmation');
|
|
|
|
var folder = this.env.folders[this.env.folder_subscribe],
|
|
node = rcmail.folder_list.get_item(this.env.folder_subscribe);
|
|
|
|
if (this.search_results && this.search_results[this.env.folder_subscribe]) {
|
|
item = this.search_results_widget.get_item(this.env.folder_subscribe);
|
|
|
|
if (item) {
|
|
this.folder_list_subscription_state(item, false);
|
|
item = $('#' + $(item).attr('id').replace(/--xsR$/, ''));
|
|
}
|
|
else
|
|
item = $('#rcmli' + rcmail.html_identifier_encode(this.env.folder_subscribe), rcmail.folder_list.container);
|
|
|
|
this.folder_list_subscription_state(item, false);
|
|
}
|
|
|
|
this.folder_list_subscription_state(node, false);
|
|
|
|
folder.subscribed = false;
|
|
};
|
|
|
|
// folder create request
|
|
this.folder_create = function(folder)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.foldercreating');
|
|
this.request('folder_create', {folder: folder}, 'folder_create_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_create_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.foldercreatenotice', 'confirmation');
|
|
|
|
// refresh folders list
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder rename request
|
|
this.folder_rename = function(folder, new_name)
|
|
{
|
|
if (folder == new_name)
|
|
return;
|
|
|
|
this.env.folder_rename = new_name;
|
|
this.req = this.set_busy(true, 'kolab_files.folderupdating');
|
|
this.request('folder_move', {folder: folder, 'new': new_name}, 'folder_rename_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_rename_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.folderupdatenotice', 'confirmation');
|
|
|
|
// refresh folders and files list
|
|
this.env.folder = this.env.folder_rename;
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder mount (external storage) request
|
|
this.folder_mount = function(data)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.foldermounting');
|
|
this.request('folder_create', data, 'folder_mount_response');
|
|
};
|
|
|
|
// folder create response handler
|
|
this.folder_mount_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.display_message('kolab_files.foldermountnotice', 'confirmation');
|
|
|
|
// refresh folders list
|
|
this.folder_list();
|
|
};
|
|
|
|
// folder delete request
|
|
this.folder_delete = function(folder)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.folderdeleting');
|
|
this.request('folder_delete', {folder: folder}, 'folder_delete_response');
|
|
};
|
|
|
|
// folder delete response handler
|
|
this.folder_delete_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
this.env.folder = null;
|
|
rcmail.enable_command('files-folder-delete', 'folder-rename', 'files-list', false);
|
|
this.display_message('kolab_files.folderdeletenotice', 'confirmation');
|
|
|
|
// refresh folders list
|
|
this.folder_list();
|
|
this.quota();
|
|
};
|
|
|
|
// quota request
|
|
this.quota = function()
|
|
{
|
|
if (rcmail.env.files_quota)
|
|
this.request('quota', {folder: this.env.folder}, 'quota_response');
|
|
};
|
|
|
|
// quota response handler
|
|
this.quota_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
rcmail.files_set_quota(response.result);
|
|
};
|
|
|
|
this.file_list = function(params)
|
|
{
|
|
if (!rcmail.gui_objects.filelist)
|
|
return;
|
|
|
|
if (!params)
|
|
params = {};
|
|
|
|
// reset all pending list requests
|
|
for (i in this.requests) {
|
|
this.requests[i].abort();
|
|
rcmail.hide_message(i);
|
|
delete this.requests[i];
|
|
}
|
|
|
|
if (params.all_folders) {
|
|
params.collection = null;
|
|
params.folder = null;
|
|
this.folder_unselect();
|
|
}
|
|
|
|
if (params.collection == undefined)
|
|
params.collection = this.env.collection;
|
|
if (params.folder == undefined)
|
|
params.folder = this.env.folder;
|
|
if (params.sort == undefined)
|
|
params.sort = this.env.sort_col;
|
|
if (params.reverse == undefined)
|
|
params.reverse = this.env.sort_reverse;
|
|
if (params.search == undefined)
|
|
params.search = this.env.search;
|
|
|
|
this.env.folder = params.folder;
|
|
this.env.collection = params.collection;
|
|
this.env.sort_col = params.sort;
|
|
this.env.sort_reverse = params.reverse;
|
|
|
|
rcmail.enable_command(rcmail.env.file_commands, false);
|
|
rcmail.enable_command(rcmail.env.file_commands_all, false);
|
|
|
|
// empty the list
|
|
this.env.file_list = [];
|
|
rcmail.file_list.clear(true);
|
|
|
|
// request
|
|
if (params.collection || params.all_folders)
|
|
this.file_list_loop(params);
|
|
else if (this.env.folder) {
|
|
params.req_id = this.set_busy(true, 'loading');
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_response');
|
|
}
|
|
};
|
|
|
|
// file list response handler
|
|
this.file_list_response = function(response)
|
|
{
|
|
if (response.req_id)
|
|
rcmail.hide_message(response.req_id);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var i = 0, list = [], table = $('#filelist');
|
|
|
|
$.each(response.result, function(key, data) {
|
|
var row = file_api.file_list_row(key, data, ++i);
|
|
rcmail.file_list.insert_row(row);
|
|
data.row = row;
|
|
data.filename = key;
|
|
list.push(data);
|
|
});
|
|
|
|
this.env.file_list = list;
|
|
rcmail.file_list.resize();
|
|
};
|
|
|
|
// call file_list request for every folder (used for search and virt. collections)
|
|
this.file_list_loop = function(params)
|
|
{
|
|
var i, folders = [], limit = Math.max(this.env.search_threads || 1, 1);
|
|
|
|
if (params.collection) {
|
|
if (!params.search)
|
|
params.search = {};
|
|
params.search['class'] = params.collection;
|
|
delete params['collection'];
|
|
}
|
|
|
|
delete params['all_folders'];
|
|
|
|
$.each(this.env.folders, function(i, f) {
|
|
if (!f.virtual)
|
|
folders.push(i);
|
|
});
|
|
|
|
this.env.folders_loop = folders;
|
|
this.env.folders_loop_params = params;
|
|
this.env.folders_loop_lock = false;
|
|
|
|
for (i=0; i<folders.length && i<limit; i++) {
|
|
params.req_id = this.set_busy(true, 'loading');
|
|
params.folder = folders.shift();
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response');
|
|
}
|
|
};
|
|
|
|
// file list response handler for loop'ed request
|
|
this.file_list_loop_response = function(response)
|
|
{
|
|
var i, folders = this.env.folders_loop,
|
|
params = this.env.folders_loop_params,
|
|
limit = Math.max(this.env.search_threads || 1, 1),
|
|
valid = this.response(response);
|
|
|
|
if (response.req_id)
|
|
rcmail.hide_message(response.req_id);
|
|
|
|
for (i=0; i<folders.length && i<limit; i++) {
|
|
params.req_id = this.set_busy(true, 'loading');
|
|
params.folder = folders.shift();
|
|
this.requests[params.req_id] = this.request('file_list', params, 'file_list_loop_response');
|
|
}
|
|
|
|
rcmail.file_list.resize();
|
|
|
|
if (!valid)
|
|
return;
|
|
|
|
this.file_list_loop_result_add(response.result);
|
|
};
|
|
|
|
// add files from list request to the table (with sorting)
|
|
this.file_list_loop_result_add = function(result)
|
|
{
|
|
// chack if result (hash-array) is empty
|
|
if (!object_is_empty(result))
|
|
return;
|
|
|
|
if (this.env.folders_loop_lock) {
|
|
setTimeout(function() { file_api.file_list_loop_result_add(result); }, 100);
|
|
return;
|
|
}
|
|
|
|
// lock table, other list responses will wait
|
|
this.env.folders_loop_lock = true;
|
|
|
|
var n, i, len, elem, list = [], rows = [],
|
|
index = this.env.file_list.length,
|
|
table = rcmail.file_list;
|
|
|
|
for (n=0, len=index; n<len; n++) {
|
|
elem = this.env.file_list[n];
|
|
for (i in result) {
|
|
if (this.sort_compare(elem, result[i]) < 0)
|
|
break;
|
|
|
|
var row = this.file_list_row(i, result[i], ++index);
|
|
table.insert_row(row, elem.row);
|
|
result[i].row = row;
|
|
result[i].filename = i;
|
|
list.push(result[i]);
|
|
delete result[i];
|
|
}
|
|
|
|
list.push(elem);
|
|
}
|
|
|
|
// add the rest of rows
|
|
$.each(result, function(key, data) {
|
|
var row = file_api.file_list_row(key, data, ++index);
|
|
table.insert_row(row);
|
|
result[key].row = row;
|
|
result[key].filename = key;
|
|
list.push(result[key]);
|
|
});
|
|
|
|
this.env.file_list = list;
|
|
this.env.folders_loop_lock = false;
|
|
};
|
|
|
|
// sort files list (without API request)
|
|
this.file_list_sort = function(col, reverse)
|
|
{
|
|
var n, len, list = this.env.file_list,
|
|
table = $('#filelist'), tbody = $('<tbody>');
|
|
|
|
this.env.sort_col = col;
|
|
this.env.sort_reverse = reverse;
|
|
|
|
if (!list || !list.length)
|
|
return;
|
|
|
|
// sort the list
|
|
list.sort(function (a, b) {
|
|
return file_api.sort_compare(a, b);
|
|
});
|
|
|
|
// add rows to the new body
|
|
for (n=0, len=list.length; n<len; n++) {
|
|
tbody.append(list[n].row);
|
|
}
|
|
|
|
// replace table bodies
|
|
$('tbody', table).replaceWith(tbody);
|
|
};
|
|
|
|
this.file_list_row = function(file, data, index)
|
|
{
|
|
var c, col, row = '';
|
|
|
|
for (c in rcmail.env.file_coltypes) {
|
|
c = rcmail.env.file_coltypes[c];
|
|
if (c == 'name')
|
|
col = '<td class="name filename ' + this.file_type_class(data.type) + '">'
|
|
+ '<span>' + escapeHTML(data.name) + '</span></td>';
|
|
else if (c == 'mtime')
|
|
col = '<td class="mtime">' + data.mtime + '</td>';
|
|
else if (c == 'size')
|
|
col = '<td class="size">' + this.file_size(data.size) + '</td>';
|
|
else if (c == 'options')
|
|
col = '<td class="options"><span></span></td>';
|
|
else
|
|
col = '<td class="' + c + '"></td>';
|
|
|
|
row += col;
|
|
}
|
|
|
|
row = $('<tr>')
|
|
.html(row)
|
|
.attr({id: 'rcmrow' + index, 'data-file': file, 'data-type': data.type});
|
|
|
|
$('td.options > span', row).click(function(e) {
|
|
kolab_files_file_edit_dialog(file);
|
|
});
|
|
|
|
// collection (or search) lists files from all folders
|
|
// display file name with full path as title
|
|
if (!this.env.folder)
|
|
$('td.name span', row).attr('title', file);
|
|
|
|
return row.get(0);
|
|
};
|
|
|
|
this.file_search = function(value, all_folders)
|
|
{
|
|
if (value) {
|
|
this.env.search = {name: value};
|
|
rcmail.command('files-list', {search: this.env.search, all_folders: all_folders});
|
|
}
|
|
else
|
|
this.search_reset();
|
|
};
|
|
|
|
this.file_search_reset = function()
|
|
{
|
|
if (this.env.search) {
|
|
this.env.search = null;
|
|
rcmail.command('files-list');
|
|
}
|
|
};
|
|
|
|
this.file_get = function(file, params)
|
|
{
|
|
if (!params)
|
|
params = {};
|
|
|
|
params.token = this.env.token;
|
|
params.file = file;
|
|
|
|
rcmail.redirect(this.env.url + this.url('file_get', params));
|
|
};
|
|
|
|
// file(s) delete request
|
|
this.file_delete = function(files)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.filedeleting');
|
|
this.request('file_delete', {file: files}, 'file_delete_response');
|
|
};
|
|
|
|
// file(s) delete response handler
|
|
this.file_delete_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var rco, dir, self = this;
|
|
|
|
this.display_message('kolab_files.filedeletenotice', 'confirmation');
|
|
|
|
if (rcmail.env.file) {
|
|
rco = rcmail.opener();
|
|
dir = this.file_path(rcmail.env.file);
|
|
|
|
// check if opener window contains files list, if not we can just close current window
|
|
if (rco && rco.file_list && (opener.file_api.env.folder == dir || !opener.file_api.env.folder))
|
|
self = opener.file_api;
|
|
else
|
|
window.close();
|
|
}
|
|
|
|
// @TODO: consider list modification "in-place" instead of full reload
|
|
self.file_list();
|
|
self.quota();
|
|
|
|
if (rcmail.env.file)
|
|
window.close();
|
|
};
|
|
|
|
// file(s) move request
|
|
this.file_move = function(files, folder)
|
|
{
|
|
if (!files || !files.length || !folder)
|
|
return;
|
|
|
|
var count = 0, list = {};
|
|
|
|
$.each(files, function(i, v) {
|
|
var name = folder + file_api.env.directory_separator + file_api.file_name(v);
|
|
|
|
if (name != v) {
|
|
list[v] = name;
|
|
count++;
|
|
}
|
|
});
|
|
|
|
if (!count)
|
|
return;
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.filemoving');
|
|
this.request('file_move', {file: list}, 'file_move_response');
|
|
};
|
|
|
|
// file(s) move response handler
|
|
this.file_move_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
if (response.result && response.result.already_exist && response.result.already_exist.length)
|
|
this.file_move_ask_user(response.result.already_exist, true);
|
|
else {
|
|
this.display_message('kolab_files.filemovenotice', 'confirmation');
|
|
this.file_list();
|
|
}
|
|
};
|
|
|
|
// file(s) copy request
|
|
this.file_copy = function(files, folder)
|
|
{
|
|
if (!files || !files.length || !folder)
|
|
return;
|
|
|
|
var count = 0, list = {};
|
|
|
|
$.each(files, function(i, v) {
|
|
var name = folder + file_api.env.directory_separator + file_api.file_name(v);
|
|
|
|
if (name != v) {
|
|
list[v] = name;
|
|
count++;
|
|
}
|
|
});
|
|
|
|
if (!count)
|
|
return;
|
|
|
|
this.req = this.set_busy(true, 'kolab_files.filecopying');
|
|
this.request('file_copy', {file: list}, 'file_copy_response');
|
|
};
|
|
|
|
// file(s) copy response handler
|
|
this.file_copy_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
if (response.result && response.result.already_exist && response.result.already_exist.length)
|
|
this.file_move_ask_user(response.result.already_exist);
|
|
else {
|
|
this.display_message('kolab_files.filecopynotice', 'confirmation');
|
|
this.quota();
|
|
}
|
|
};
|
|
|
|
// when file move/copy operation returns file-exists error
|
|
// this displays a dialog where user can decide to skip
|
|
// or overwrite destination file(s)
|
|
this.file_move_ask_user = function(list, move)
|
|
{
|
|
var file = list[0], buttons = {},
|
|
text = rcmail.gettext('kolab_files.filemoveconfirm').replace('$file', file.dst)
|
|
dialog = $('<div></div>');
|
|
|
|
buttons[rcmail.gettext('kolab_files.fileoverwrite')] = function() {
|
|
var file = list.shift(), f = {},
|
|
action = move ? 'file_move' : 'file_copy';
|
|
|
|
f[file.src] = file.dst;
|
|
file_api.file_move_ask_list = list;
|
|
file_api.file_move_ask_mode = move;
|
|
dialog.dialog('destroy').remove();
|
|
file_api.req = file_api.set_busy(true, move ? 'kolab_files.filemoving' : 'kolab_files.filecopying');
|
|
file_api.request(action, {file: f, overwrite: 1}, 'file_move_ask_user_response');
|
|
};
|
|
|
|
if (list.length > 1)
|
|
buttons[rcmail.gettext('kolab_files.fileoverwriteall')] = function() {
|
|
var f = {}, action = move ? 'file_move' : 'file_copy';
|
|
|
|
$.each(list, function() { f[this.src] = this.dst; });
|
|
dialog.dialog('destroy').remove();
|
|
file_api.req = file_api.set_busy(true, move ? 'kolab_files.filemoving' : 'kolab_files.filecopying');
|
|
file_api.request(action, {file: f, overwrite: 1}, action + '_response');
|
|
};
|
|
|
|
var skip_func = function() {
|
|
list.shift();
|
|
dialog.dialog('destroy').remove();
|
|
|
|
if (list.length)
|
|
file_api.file_move_ask_user(list, move);
|
|
else if (move)
|
|
file_api.file_list();
|
|
};
|
|
|
|
buttons[rcmail.gettext('kolab_files.fileskip')] = skip_func;
|
|
|
|
if (list.length > 1)
|
|
buttons[rcmail.gettext('kolab_files.fileskipall')] = function() {
|
|
dialog.dialog('destroy').remove();
|
|
if (move)
|
|
file_api.file_list();
|
|
};
|
|
|
|
// open jquery UI dialog
|
|
kolab_dialog_show(dialog.html(text), {
|
|
close: skip_func,
|
|
buttons: buttons,
|
|
minWidth: 400,
|
|
width: 400
|
|
});
|
|
};
|
|
|
|
// file move (with overwrite) response handler
|
|
this.file_move_ask_user_response = function(response)
|
|
{
|
|
var move = this.file_move_ask_mode, list = this.file_move_ask_list;
|
|
|
|
this.response(response);
|
|
|
|
if (list && list.length)
|
|
this.file_move_ask_user(list, mode);
|
|
else {
|
|
this.display_message('kolab_files.file' + (move ? 'move' : 'copy') + 'notice', 'confirmation');
|
|
if (move)
|
|
this.file_list();
|
|
}
|
|
};
|
|
|
|
// file(s) rename request
|
|
this.file_rename = function(oldfile, newfile)
|
|
{
|
|
this.req = this.set_busy(true, 'kolab_files.fileupdating');
|
|
this.request('file_move', {file: oldfile, 'new': newfile}, 'file_rename_response');
|
|
};
|
|
|
|
// file(s) move response handler
|
|
this.file_rename_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// @TODO: we could update metadata instead
|
|
this.file_list();
|
|
};
|
|
|
|
// file upload request
|
|
this.file_upload = function(form)
|
|
{
|
|
var form = $(form),
|
|
field = $('input[type=file]', form).get(0),
|
|
files = field.files ? field.files.length : field.value ? 1 : 0;
|
|
|
|
if (!files || !this.file_upload_size_check(field.files))
|
|
return;
|
|
|
|
// submit form and read server response
|
|
this.file_upload_form(form, 'file_upload', function(event) {
|
|
var doc, response;
|
|
try {
|
|
doc = this.contentDocument ? this.contentDocument : this.contentWindow.document;
|
|
response = doc.body.innerHTML;
|
|
// response may be wrapped in <pre> tag
|
|
if (response.slice(0, 5).toLowerCase() == '<pre>' && response.slice(-6).toLowerCase() == '</pre>') {
|
|
response = doc.body.firstChild.firstChild.nodeValue;
|
|
}
|
|
response = eval('(' + response + ')');
|
|
}
|
|
catch (err) {
|
|
response = {status: 'ERROR'};
|
|
}
|
|
|
|
file_api.file_upload_progress_stop(event.data.ts);
|
|
|
|
// refresh the list on upload success
|
|
file_api.file_upload_response(response);
|
|
});
|
|
};
|
|
|
|
// refresh the list on upload success
|
|
this.file_upload_response = function(response)
|
|
{
|
|
if (this.response_parse(response)) {
|
|
this.file_list();
|
|
this.quota();
|
|
}
|
|
};
|
|
|
|
// check upload max size
|
|
this.file_upload_size_check = function(files)
|
|
{
|
|
var i, size = 0, maxsize = rcmail.env.files_max_upload;
|
|
|
|
if (maxsize && files) {
|
|
for (i=0; i < files.length; i++)
|
|
size += files[i].size || files[i].fileSize;
|
|
|
|
if (size > maxsize) {
|
|
alert(rcmail.get_label('kolab_files.uploadsizeerror').replace('$size', kolab_files_file_size(maxsize)));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
// post the given form to a hidden iframe
|
|
this.file_upload_form = function(form, action, onload)
|
|
{
|
|
var ts = new Date().getTime(),
|
|
frame_name = 'fileupload' + ts;
|
|
|
|
// upload progress support
|
|
if (rcmail.env.files_progress_name) {
|
|
var fname = rcmail.env.files_progress_name,
|
|
field = $('input[name='+fname+']', form);
|
|
|
|
if (!field.length) {
|
|
field = $('<input>').attr({type: 'hidden', name: fname});
|
|
field.prependTo(form);
|
|
}
|
|
|
|
field.val(ts);
|
|
this.file_upload_progress(ts, true);
|
|
}
|
|
|
|
rcmail.display_progress({name: ts});
|
|
|
|
// have to do it this way for IE
|
|
// otherwise the form will be posted to a new window
|
|
if (document.all) {
|
|
var html = '<iframe id="'+frame_name+'" name="'+frame_name+'"'
|
|
+ ' src="' + rcmail.assets_path('program/resources/blank.gif') + '"'
|
|
+ ' style="width:0;height:0;visibility:hidden;"></iframe>';
|
|
document.body.insertAdjacentHTML('BeforeEnd', html);
|
|
}
|
|
// for standards-compliant browsers
|
|
else
|
|
$('<iframe>')
|
|
.attr({name: frame_name, id: frame_name})
|
|
.css({border: 'none', width: 0, height: 0, visibility: 'hidden'})
|
|
.appendTo(document.body);
|
|
|
|
// handle upload errors, parsing iframe content in onload
|
|
$('#'+frame_name).on('load', {ts:ts}, onload);
|
|
|
|
$(form).attr({
|
|
target: frame_name,
|
|
action: this.env.url + this.url(action, {folder: this.env.folder, token: this.env.token}),
|
|
method: 'POST'
|
|
}).attr(form.encoding ? 'encoding' : 'enctype', 'multipart/form-data')
|
|
.submit();
|
|
};
|
|
|
|
// handler when files are dropped to a designated area.
|
|
// compose a multipart form data and submit it to the server
|
|
this.file_drop = function(e)
|
|
{
|
|
var files = e.target.files || e.dataTransfer.files;
|
|
|
|
if (!files || !files.length || !this.file_upload_size_check(files))
|
|
return;
|
|
|
|
// prepare multipart form data composition
|
|
var ts = new Date().getTime(),
|
|
formdata = window.FormData ? new FormData() : null,
|
|
fieldname = 'file[]',
|
|
boundary = '------multipartformboundary' + (new Date).getTime(),
|
|
dashdash = '--', crlf = '\r\n',
|
|
multipart = dashdash + boundary + crlf;
|
|
|
|
// inline function to submit the files to the server
|
|
var submit_data = function() {
|
|
var multiple = files.length > 1;
|
|
|
|
rcmail.display_progress({name: ts});
|
|
if (rcmail.env.files_progress_name)
|
|
file_api.file_upload_progress(ts, true);
|
|
|
|
// complete multipart content and post request
|
|
multipart += dashdash + boundary + dashdash + crlf;
|
|
|
|
$.ajax({
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
url: file_api.env.url + file_api.url('file_upload', {folder: file_api.env.folder}),
|
|
contentType: formdata ? false : 'multipart/form-data; boundary=' + boundary,
|
|
processData: false,
|
|
timeout: 0, // disable default timeout set in ajaxSetup()
|
|
data: formdata || multipart,
|
|
headers: {'X-Session-Token': file_api.env.token},
|
|
success: function(data) {
|
|
file_api.file_upload_progress_stop(ts);
|
|
file_api.file_upload_response(data);
|
|
},
|
|
error: function(o, status, err) {
|
|
file_api.file_upload_progress_stop(ts);
|
|
rcmail.http_error(o, status, err);
|
|
},
|
|
xhr: function() {
|
|
var xhr = jQuery.ajaxSettings.xhr();
|
|
if (!formdata && xhr.sendAsBinary)
|
|
xhr.send = xhr.sendAsBinary;
|
|
return xhr;
|
|
}
|
|
});
|
|
};
|
|
|
|
// upload progress supported (and handler exists)
|
|
// add progress ID to the request - need to be added before files
|
|
if (rcmail.env.files_progress_name) {
|
|
if (formdata)
|
|
formdata.append(rcmail.env.files_progress_name, ts);
|
|
else
|
|
multipart += 'Content-Disposition: form-data; name="' + rcmail.env.files_progress_name + '"'
|
|
+ crlf + crlf + ts + crlf + dashdash + boundary + crlf;
|
|
}
|
|
|
|
// get contents of all dropped files
|
|
var f, j, i = 0, last = files.length - 1;
|
|
for (j = 0; j <= last && (f = files[i]); i++) {
|
|
if (!f.name) f.name = f.fileName;
|
|
if (!f.size) f.size = f.fileSize;
|
|
if (!f.type) f.type = 'application/octet-stream';
|
|
|
|
// file name contains non-ASCII characters, do UTF8-binary string conversion.
|
|
if (!formdata && /[^\x20-\x7E]/.test(f.name))
|
|
f.name_bin = unescape(encodeURIComponent(f.name));
|
|
|
|
// do it the easy way with FormData (FF 4+, Chrome 5+, Safari 5+)
|
|
if (formdata) {
|
|
formdata.append(fieldname, f);
|
|
if (j == last)
|
|
return submit_data();
|
|
}
|
|
// use FileReader supporetd by Firefox 3.6
|
|
else if (window.FileReader) {
|
|
var reader = new FileReader();
|
|
|
|
// closure to pass file properties to async callback function
|
|
reader.onload = (function(file, j) {
|
|
return function(e) {
|
|
multipart += 'Content-Disposition: form-data; name="' + fieldname + '"';
|
|
multipart += '; filename="' + (f.name_bin || file.name) + '"' + crlf;
|
|
multipart += 'Content-Length: ' + file.size + crlf;
|
|
multipart += 'Content-Type: ' + file.type + crlf + crlf;
|
|
multipart += reader.result + crlf;
|
|
multipart += dashdash + boundary + crlf;
|
|
|
|
if (j == last) // we're done, submit the data
|
|
return submit_data();
|
|
}
|
|
})(f,j);
|
|
reader.readAsBinaryString(f);
|
|
}
|
|
|
|
j++;
|
|
}
|
|
};
|
|
|
|
// upload progress requests
|
|
this.file_upload_progress = function(id, init)
|
|
{
|
|
if (init && id)
|
|
this.uploads[id] = this.env.folder;
|
|
|
|
setTimeout(function() {
|
|
if (id && file_api.uploads[id])
|
|
file_api.request('upload_progress', {id: id}, 'file_upload_progress_response');
|
|
}, rcmail.env.files_progress_time * 1000);
|
|
};
|
|
|
|
// upload progress response
|
|
this.file_upload_progress_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var param = response.result;
|
|
|
|
if (!param.id || !this.uploads[param.id])
|
|
return;
|
|
|
|
if (param.total) {
|
|
param.name = param.id;
|
|
|
|
if (!param.done)
|
|
param.text = kolab_files_progress_str(param);
|
|
|
|
rcmail.display_progress(param);
|
|
}
|
|
|
|
if (!param.done && param.total)
|
|
this.file_upload_progress(param.id);
|
|
else
|
|
delete this.uploads[param.id];
|
|
};
|
|
|
|
this.file_upload_progress_stop = function(id)
|
|
{
|
|
if (id) {
|
|
delete this.uploads[id];
|
|
rcmail.display_progress({name: id});
|
|
}
|
|
};
|
|
|
|
// open file in new window, using file API viewer
|
|
this.file_open = function(file, viewer)
|
|
{
|
|
var href = '?' + $.param({_task: 'files', _action: 'open', file: file, viewer: viewer == 2 ? 1 : 0});
|
|
rcmail.open_window(href, false, true);
|
|
};
|
|
|
|
// save file
|
|
this.file_save = function(file, content)
|
|
{
|
|
rcmail.enable_command('files-save', false);
|
|
// because we currently can edit only text files
|
|
// and we do not expect them to be very big, we save
|
|
// file in a very simple way, no upload progress, etc.
|
|
this.req = this.set_busy(true, 'saving');
|
|
this.request('file_update', {file: file, content: content, info: 1}, 'file_save_response');
|
|
};
|
|
|
|
// file save response handler
|
|
this.file_save_response = function(response)
|
|
{
|
|
rcmail.enable_command('files-save', true);
|
|
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
// update file properties table
|
|
var table = $('#fileinfobox table'), file = response.result;
|
|
|
|
if (file) {
|
|
$('td.filetype', table).text(file.type);
|
|
$('td.filesize', table).text(this.file_size(file.size));
|
|
$('td.filemtime', table).text(file.mtime);
|
|
}
|
|
};
|
|
|
|
// handle auth errors on folder list
|
|
this.folder_list_auth_errors = function(result)
|
|
{
|
|
if (result && result.auth_errors) {
|
|
if (!this.auth_errors)
|
|
this.auth_errors = {};
|
|
|
|
$.extend(this.auth_errors, result.auth_errors);
|
|
}
|
|
|
|
// ask for password to the first storage on the list
|
|
$.each(this.auth_errors || [], function(i, v) {
|
|
file_api.folder_list_auth_dialog(i, v);
|
|
return false;
|
|
});
|
|
};
|
|
|
|
// create dialog for user credentials of external storage
|
|
this.folder_list_auth_dialog = function(label, driver)
|
|
{
|
|
var args = {width: 400, height: 300, buttons: {}},
|
|
dialog = $('#files-folder-auth-dialog'),
|
|
content = this.folder_list_auth_form(driver);
|
|
|
|
dialog.find('table.propform').remove();
|
|
$('.auth-options', dialog).before(content);
|
|
|
|
args.buttons[this.t('kolab_files.save')] = function() {
|
|
var data = {folder: label, list: 1};
|
|
|
|
$('input', dialog).each(function() {
|
|
data[this.name] = this.type == 'checkbox' && !this.checked ? '' : this.value;
|
|
});
|
|
|
|
file_api.open_dialog = this;
|
|
file_api.req = file_api.set_busy(true, 'kolab_files.authenticating');
|
|
file_api.request('folder_auth', data, 'folder_auth_response');
|
|
};
|
|
|
|
args.buttons[this.t('kolab_files.cancel')] = function() {
|
|
delete file_api.auth_errors[label];
|
|
kolab_dialog_close(this);
|
|
// go to the next one
|
|
file_api.folder_list_auth_errors();
|
|
};
|
|
|
|
args.title = this.t('kolab_files.folderauthtitle').replace('$title', label);
|
|
|
|
// show dialog window
|
|
kolab_dialog_show(dialog, args, function() {
|
|
// focus first empty input
|
|
$('input', dialog).each(function() {
|
|
if (!this.value) {
|
|
this.focus();
|
|
return false;
|
|
}
|
|
});
|
|
});
|
|
};
|
|
|
|
// folder_auth handler
|
|
this.folder_auth_response = function(response)
|
|
{
|
|
if (!this.response(response))
|
|
return;
|
|
|
|
var folders, found,
|
|
folder = response.result.folder,
|
|
id = 'rcmli' + rcmail.html_identifier_encode(folder),
|
|
parent = $('#' + id);
|
|
|
|
// try parent window if the folder element does not exist
|
|
if (!parent.length && window.parent && window.parent.rcmail) {
|
|
parent = $('#' + id, window.parent.document.body);
|
|
}
|
|
|
|
delete this.auth_errors[folder];
|
|
kolab_dialog_close(this.open_dialog);
|
|
|
|
// go to the next one
|
|
this.folder_list_auth_errors();
|
|
|
|
// parse result
|
|
folders = this.folder_list_parse(response.result.list);
|
|
delete folders[folder]; // remove root added in folder_list_parse()
|
|
|
|
// add folders from the external source to the list
|
|
$.each(folders, function(i, f) {
|
|
file_api.folder_list_row(i, f, parent.get(0));
|
|
found = true;
|
|
});
|
|
|
|
// reset folders list widget
|
|
if (found)
|
|
rcmail.folder_list.reset(true);
|
|
|
|
// add tree icons
|
|
// this.folder_list_tree(folders);
|
|
|
|
$.extend(this.env.folders, folders);
|
|
};
|
|
|
|
// returns content of the external storage authentication form
|
|
this.folder_list_auth_form = function(driver)
|
|
{
|
|
var rows = [];
|
|
|
|
$.each(driver.form, function(fi, fv) {
|
|
var id = 'authinput' + fi,
|
|
attrs = {type: fi.match(/pass/) ? 'password' : 'text', size: 25, name: fi, id: id},
|
|
input = $('<input>').attr(attrs);
|
|
|
|
if (driver.form_values && driver.form_values[fi])
|
|
input.attr({value: driver.form_values[fi]});
|
|
|
|
rows.push($('<tr>')
|
|
.append($('<td class="title">').append($('<label>').attr('for', id).text(fv)))
|
|
.append($('<td>').append(input))
|
|
);
|
|
});
|
|
|
|
return $('<table class="propform">').append(rows);
|
|
};
|
|
};
|