diff --git a/plugins/kolab_files/kolab_files.js b/plugins/kolab_files/kolab_files.js index 6e7ca0a9..2ed926fa 100644 --- a/plugins/kolab_files/kolab_files.js +++ b/plugins/kolab_files/kolab_files.js @@ -1,3032 +1,3061 @@ /** * Kolab files plugin * * @author Aleksander Machniak * * @licstart The following is the entire license notice for the * JavaScript code in this file. * * Copyright (C) 2011-2015, Kolab Systems AG * * 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 . * * @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 = $('') .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.buttons')); }); } 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.buttons')); 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.buttons')); 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', 'files-rename']; // "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.env.action == 'edit') { rcmail.enable_command('files-get', 'files-delete', rcmail.env.file); if (rcmail.env.action == 'edit' && rcmail.env.file_data.viewer && rcmail.env.file_data.viewer.manticore) manticore = new manticore_api({ iframe: $('#fileframe').get(0), export_menu: rcmail.gui_objects.exportmenu ? $('ul', rcmail.gui_objects.exportmenu).get(0) : null, title_input: $('#document-title').get(0), members_list: $('#members').get(0), photo_url: '?_task=addressbook&_action=photo&_email=%email', photo_default_url: rcmail.env.photo_placeholder, ready: function(data) { manticore_init(); }, set_busy: function(state, message) { return rcmail.set_busy(state, message ? 'kolab_files.' + message : ''); }, hide_message: function(id) { return rcmail.hide_message(id); }, display_message: function(label, type) { return rcmail.display_message('kolab_files.' + label, type); }, gettext: function(label) { return rcmail.get_label('kolab_files.' + label); } }); if (rcmail.env.action == 'open') { // initialize folders list (for dialogs) file_api.folder_list(); // get ongoing sessions file_api.request('folder_info', {folder: file_api.file_path(rcmail.env.file), sessions: 1}, 'folder_info_response'); } } 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 = $('') .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({writable: 1}); 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 = '' + rcmail.get_label('kolab_files.attaching') + '', 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 file_api.folder_select_element(select, {empty: true, writable: true}); }; // folder edit dialog function kolab_files_folder_edit_dialog() { var dialog = $('#files-folder-edit-dialog'), buttons = {}, 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 file_api.folder_select_element(select, {selected: path, empty: true}); }; // 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 edit dialog function kolab_files_file_edit_dialog(file, sessions, readonly) { var content = [], items = [], height = 300; dialog = $('#files-file-edit-dialog'), buttons = {}, name = file_api.file_name(file), title = rcmail.gettext('kolab_files.editfiledialog'), mainaction = rcmail.gettext('kolab_files.select'), item_fn = function(id, txt, classes) { return $('
').text(rcmail.gettext('kolab_files.editfilesessions'))); // first display owned sessions, then invited, other at the end $.each(sessions, function() { if (this.is_owner) { var txt = rcmail.gettext('kolab_files.ownedsession'); items.push(item_fn(this.id, txt, 'owner')); } }); if (items.length == 1) items.push(item_fn(0, rcmail.gettext('kolab_files.newsession' + (readonly ? 'ro' : '')))); $.each(sessions, function() { if (this.is_invited) { var txt = rcmail.gettext('kolab_files.invitedsession').replace('$user', this.owner); items.push(item_fn(this.id, txt, 'invited')); } }); $.each(sessions, function() { if (!this.is_owner && !this.is_invited) { var txt = rcmail.gettext('kolab_files.joinsession').replace('$user', this.owner); items.push(item_fn(this.id, txt)); } }); // check the first option $('input', items[1]).attr('checked', true); $('div', dialog).html(items); // if there's only one session and it's owned, skip the dialog if (!readonly && items.length == 2 && $('input:checked', dialog).parent().is('.owner')) return select_fn(); } // no ongoing session, folder is readonly warning else { title = rcmail.gettext('kolab_files.editfilerotitle'); height = 150; $('div', dialog).text(rcmail.gettext('kolab_files.editfilero')); mainaction = rcmail.gettext('kolab_files.create'); } buttons[mainaction] = function() { select_fn(this); }; buttons[rcmail.gettext('kolab_files.cancel')] = function () { kolab_dialog_close(this); }; // show dialog window kolab_dialog_show(dialog, { title: title, buttons: buttons, button_classes: ['mainaction'], minHeight: height - 100, height: height }); }; // file rename dialog function kolab_files_file_rename_dialog(file) { var dialog = $('#files-file-rename-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; 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.renamefile'), buttons: buttons, button_classes: ['mainaction'], minHeight: 100, height: 200 }); }; // file creation (or cloning) dialog function kolab_files_file_create_dialog(file) { var buttons = {}, action = file ? 'copy' : 'create', dialog = $('#files-file-create-dialog'), type_select = $('select[name="type"]', dialog), select = $('select[name="parent"]', dialog).html(''), input = $('input[name="name"]', dialog).val(''), create_func = function(dialog, editaction) { var sel, folder = select.val(), type = type_select.val(), name = input.val(); if (!name || !folder) return; if (!/\.[a-z0-9]{1,5}$/.test(name)) { name += '.' + rcmail.env.file_extensions[type]; } name = folder + file_api.env.directory_separator + name; // get type of cloned file if (file) { if (rcmail.env.file_data) type = rcmail.env.file_data.type; else { sel = rcmail.file_list.get_selection(); type = $('#rcmrow' + sel[0]).data('type'); } } file_api.file_create(name, type, editaction, file); kolab_dialog_close(dialog); }; buttons[rcmail.gettext('kolab_files.' + action + 'andedit')] = function() { create_func(this, true); }; if (action == 'create') { buttons[rcmail.gettext('kolab_files.create')] = function() { create_func(this); }; type_select.parent('tr').show(); } else { input.val(file_api.file_name(file)); type_select.parent('tr').hide(); } 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.' + action + 'file'), buttons: buttons, button_classes: ['mainaction'], minHeight: 150, height: 250 }); // build folder selector file_api.folder_select_element(select, {writable: true}); }; 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 = $(''), 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 function kolab_files_list_coltypes() { 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(); }; function kolab_files_set_list_options(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= 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}); }; function kolab_files_list_dblclick(list) { rcmail.command('files-open'); }; function kolab_files_list_select(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; if (selected == 1) { // get file mimetype var elem = $('tr.selected', list.list), type = elem.data('type'), folder = file_api.file_path(elem.data('file')); rcmail.env.viewer = file_api.file_type_supported(type, rcmail.env.files_caps); if (!file_api.is_writable(folder)) rcmail.enable_command('files-delete', 'files-rename', false); } else rcmail.env.viewer = 0; rcmail.enable_command('files-edit', (rcmail.env.viewer & 4) == 4); rcmail.enable_command('files-open', rcmail.env.viewer); }; function kolab_files_list_keypress(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'); }; function kolab_files_drag_start(e) { rcmail.env.drag_target = null; if (rcmail.folder_list) rcmail.folder_list.drag_start(); }; function kolab_files_drag_end(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); } } }; function kolab_files_drag_move(e) { if (rcmail.folder_list) { var mouse = rcube_event.get_mouse_pos(e); rcmail.env.drag_target = rcmail.folder_list.intersects(mouse, true); } }; function kolab_files_drag_menu_action(command) { var menu = rcmail.gui_objects.file_dragmenu; if (menu) $(menu).hide(); rcmail.command(command, rcmail.env.drag_target); }; function kolab_files_selected() { 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; }; function kolab_files_frame_load(frame) { - var win = frame.contentWindow; + var win = frame.contentWindow, + info = rcmail.env.file_data; try { rcmail.file_editor = win.file_editor && win.file_editor.editable ? win.file_editor : null; } catch (e) {}; // on edit page switch immediately to edit mode if (rcmail.file_editor && rcmail.env.action == 'edit') rcmail.files_edit(); rcmail.enable_command('files-edit', rcmail.file_editor - || (rcmail.env.file_data.viewer && rcmail.env.file_data.viewer.manticore)); + || (info && info.viewer && info.viewer.manticore)); rcmail.enable_command('files-print', (rcmail.file_editor && rcmail.file_editor.printable) - || (rcmail.env.file_data && /^image\//i.test(rcmail.env.file_data.type))); - + || (info && /^image\//i.test(info.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) function kolab_files_drag_drop_init(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.is_writable()) 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 function kolab_files_drag_hover(e) { if (!file_api.is_writable()) 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 function kolab_files_file_size(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; }; function kolab_files_progress_str(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); }; /**********************************************************/ /********* Manticore editor functionality **********/ /**********************************************************/ // Initialize document toolbar functionality function manticore_init() { + var info = rcmail.env.file_data; + rcmail.enable_command('document-save', 'document-export', true); + rcmail.enable_command('files-close', info && info.session && info.session.is_owner); }; rcube_webmail.prototype.document_save = function() { manticore.save(); }; rcube_webmail.prototype.document_export = function(type) { manticore.export(type || 'odt'); }; /***********************************************************/ /********** 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(session) { var files, readonly, sessions, file = this.env.file, params = {action: 'edit'}; if (!file && !this.env.action) { files = kolab_files_selected(); if (files.length == 1) file = files[0]; } // check if the folder is read-only or there are ongoing sessions // in such cases display dialog for the user to decide what to do if (!session) { sessions = file_api.file_sessions(file); if (sessions.length || (readonly = !file_api.is_writable(file_api.file_path(file)))) { kolab_files_file_edit_dialog(file, sessions, readonly); return; } } else if (session !== true) params.session = session; if (this.file_editor && !session) { this.file_editor.enable(); this.enable_command('files-save', true); } else if (this.env.file) { var viewer = file_api.file_type_supported(this.env.file_data.type, this.env.files_caps); params.local = true; file_api.file_open(file, viewer, params); } else if (file) { file_api.file_open(file, this.env.viewer, params); } }; +// close editing session +rcube_webmail.prototype.files_close = function() +{ + // @todo: check document "unsaved changes" state and display a warning + file_api.document_delete(this.env.file_data.session.id); +}; + 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.files_create = function() { kolab_files_file_create_dialog(); }; rcube_webmail.prototype.files_rename = function() { var files = kolab_files_selected(); kolab_files_file_rename_dialog(files[0]); }; 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); }; // check if specified/current folder/view is writable this.is_writable = function(folder) { if (!folder) folder = this.env.folder; if (!folder) return false; var all_folders = $.extend({}, this.env.folders, this.search_results); if (!all_folders[folder] || all_folders[folder].readonly || all_folders[folder].virtual) return false; return true; }; // folders list request this.folder_list = function(params) { if (!params) params = {} params.permissions = 1; this.req = this.set_busy(true, 'loading'); this.request('folder_list', this.list_params = params, '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 = $('
    '), 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 = $('
  • '); row.attr('id', 'rcmli' + rcmail.html_identifier_encode('folder-collection-' + n)) .append($('
    ').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('readonly', node.classes) == -1 && $.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); rcmail.enable_command('files-create', true); // add tree icons // this.folder_list_tree(this.env.folders); // handle authentication errors on external sources if (elem.length) 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', !is_collection); rcmail.enable_command('files-upload', !is_collection && this.is_writable()); 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, classes = ['mailbox'], row = $('
  • '), id = 'rcmli' + rcmail.html_identifier_encode(i); row.attr('id', id).append($('').text(folder.name)); if (folder.virtual) classes.push('virtual'); else { if (folder.subscribed !== undefined) row.append(this.folder_list_subscription_button(folder.subscribed)); if (folder.readonly) classes.push('readonly'); } row.addClass(classes.join(' ')); 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 = $('
    ').attr('class', 'treetoggle' + (collapsed ? ' collapsed' : ' expanded')) .html(' ').appendTo(parent); sublist = $('