diff --git a/plugins/kolab_files/kolab_files.js b/plugins/kolab_files/kolab_files.js index ea80a55f..0f922a76 100644 --- a/plugins/kolab_files/kolab_files.js +++ b/plugins/kolab_files/kolab_files.js @@ -30,22 +30,21 @@ window.rcmail && rcmail.addEventListener('init', function() { // mail compose if (rcmail.env.action == 'compose') { var elem = $('#compose-attachments > div'), - input = $(''); - - input.val(rcmail.gettext('kolab_files.fromcloud')) - .click(function() { kolab_files_selector_dialog(); }) - .appendTo(elem); + 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, -// draggable: true, keyboard: true, column_movable: false, dblclick_time: rcmail.dblclick_time }); - rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); }); - rcmail.file_list.addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); }); + rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); }) + .addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); }); rcmail.gui_objects.filelist.parentNode.onmousedown = function(e){ return kolab_files_click_on_list(e); }; rcmail.enable_command('files-sort', 'files-search', 'files-search-reset', true); @@ -90,16 +89,16 @@ window.rcmail && rcmail.addEventListener('init', function() { rcmail.file_list.addEventListener('dragstart', function(o){ p.drag_start(o); }); rcmail.file_list.addEventListener('dragmove', function(e){ p.drag_move(e); }); */ - rcmail.file_list.addEventListener('dblclick', function(o){ kolab_files_list_dblclick(o); }); - rcmail.file_list.addEventListener('select', function(o){ kolab_files_list_select(o); }); - rcmail.file_list.addEventListener('dragend', function(e){ kolab_files_drag_end(e); }); - rcmail.file_list.addEventListener('column_replace', function(e){ kolab_files_set_coltypes(e); }); - rcmail.file_list.addEventListener('listupdate', function(e){ rcmail.triggerEvent('listupdate', e); }); + 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('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); }); -// document.onmouseup = function(e){ return p.doc_mouse_up(e); }; - rcmail.gui_objects.filelist.parentNode.onmousedown = function(e){ return kolab_files_click_on_list(e); }; + rcmail.gui_objects.filelist.parentNode.onmousedown = function(e) { return kolab_files_click_on_list(e); }; - rcmail.enable_command('menu-open', 'menu-save', 'files-sort', 'files-search', 'files-search-reset', true); + 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(); @@ -154,7 +153,7 @@ 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) || rcmail.env.files_token; + return window.parent && parent.rcmail && parent.rcmail.env.files_token ? parent.rcmail.env.files_token : rcmail.env.files_token; }; // folder selection dialog @@ -164,11 +163,20 @@ function kolab_directory_selector_dialog(id) input = $('#file-save-as-input'), form = $('#file-save-as'), list = $('#folderlistbox'), - buttons = {}, label = 'saveto'; + buttons = {}, label = 'saveto', + win = window, fn; // attachment is specified if (id) { - var attach = $('#attach'+id), filename = attach.attr('title') || attach.text(); + var attach = $('#attach' + id + '> a').first(), + filename = attach.attr('title'); + + if (!filename) { + attach = attach.clone(); + $('.attachment-size', attach).remove(); + filename = attach.text(); + } + form.show(); dialog.addClass('saveas'); input.val(filename); @@ -186,6 +194,8 @@ function kolab_directory_selector_dialog(id) label = 'saveall'; } + $('#foldercreatelink').attr('tabindex', 0); + buttons[rcmail.gettext('kolab_files.save')] = function () { var lock = rcmail.set_busy(true, 'saving'), request = { @@ -201,12 +211,20 @@ function kolab_directory_selector_dialog(id) } rcmail.http_post('plugin.kolab_files', request, lock); - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; + buttons[rcmail.gettext('kolab_files.cancel')] = function () { - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; + if (!rcmail.env.folders_loaded) { + fn = function() { + file_api.folder_list(); + rcmail.env.folders_loaded = true; + }; + } + // show dialog window kolab_dialog_show(dialog, { title: rcmail.gettext('kolab_files.' + label), @@ -215,11 +233,14 @@ function kolab_directory_selector_dialog(id) minHeight: 300, height: 350, width: 300 - }); + }, fn); - if (!rcmail.env.folders_loaded) { - file_api.folder_list(); - rcmail.env.folders_loaded = true; + // "enable" folder creation when dialog is displayed in parent window + if (rcmail.is_framed() && !parent.rcmail.folder_create) { + parent.rcmail.enable_command('folder-create', true); + parent.rcmail.folder_create = function() { + win.kolab_files_folder_create_dialog(); + }; } }; @@ -234,7 +255,7 @@ function kolab_files_selector_dialog() list.push($(this).data('file')); }); - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); if (list.length) { // display upload indicator and cancel button @@ -252,8 +273,9 @@ function kolab_files_selector_dialog() }); } }; + buttons[rcmail.gettext('kolab_files.cancel')] = function () { - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; // show dialog window @@ -270,8 +292,9 @@ function kolab_files_selector_dialog() file_api.folder_list(); rcmail.env.files_loaded = true; } - else + else { rcmail.file_list.clear_selection(); + } }; function kolab_files_attach_menu_open(p) @@ -306,10 +329,11 @@ function kolab_files_folder_create_dialog() folder += name; file_api.folder_create(folder); - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; + buttons[rcmail.gettext('kolab_files.cancel')] = function () { - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; // show dialog window @@ -358,10 +382,10 @@ function kolab_files_file_edit_dialog(file) // @TODO: now we only update filename if (name != file) file_api.file_rename(file, name); - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; buttons[rcmail.gettext('kolab_files.cancel')] = function () { - dialog.dialog('destroy').hide(); + kolab_dialog_close(this); }; // Fix submitting form with Enter @@ -374,11 +398,11 @@ function kolab_files_file_edit_dialog(file) }); }; -function kolab_dialog_show(dialog, params) +function kolab_dialog_show(content, params, onopen) { params = $.extend({ modal: true, - resizable: !bw.ie6, + resizable: true, closeOnEscape: (!bw.ie6 && !bw.ie7), // disabled for performance reasons minWidth: 400, minHeight: 300, @@ -386,7 +410,36 @@ function kolab_dialog_show(dialog, params) height: 400 }, params || {}); - dialog.dialog(params).show(); + // 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('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 @@ -396,6 +449,12 @@ function kolab_dialog_submit_handler() 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) { @@ -407,7 +466,7 @@ function kolab_files_upload_input(button) 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')}) + 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 @@ -579,6 +638,17 @@ kolab_files_list_select = function(list) 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_end = function(e) { var folder = $('#files-folder-list li.droptarget').removeClass('droptarget'); @@ -791,6 +861,11 @@ rcube_webmail.prototype.files_set_quota = function(p) this.set_quota(p); }; +rcube_webmail.prototype.folder_create = function() +{ + kolab_files_folder_create_dialog(); +}; + /**********************************************************/ /********* Files API handler **********/ @@ -850,6 +925,12 @@ function kolab_files_ui() list = $(''), collections = !rcmail.env.action.match(/^(preview|show)$/) ? ['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) { + elem = $('#files-folder-list', window.parent.document.body); + } + elem.html('').append(list); this.env.folders = this.folder_list_parse(response.result); @@ -868,7 +949,9 @@ function kolab_files_ui() if (f.virtual) row.addClass('virtual'); else - row.click(function() { file_api.folder_select(i); }) + row.attr('tabindex', 0) + .keypress(function(e) { if (e.which == 13 || e.which == 32) file_api.folder_select(i); }) + .click(function() { file_api.folder_select(i); }) .mouseenter(function() { if (rcmail.file_list && rcmail.file_list.drag_active && !$(this).hasClass('selected')) $(this).addClass('droptarget'); @@ -888,7 +971,7 @@ function kolab_files_ui() $.each(collections, function(i, n) { var row = $('
  • '); - row.attr('id', 'folder-collection-' + n) + row.attr({id: 'folder-collection-' + n, tabindex: 0}) .append($('').text(rcmail.gettext('kolab_files.collection_' + n))) .click(function() { file_api.folder_select(n, true); }); @@ -909,11 +992,17 @@ function kolab_files_ui() this.folder_select = function(folder, is_collection) { - var list = $('#files-folder-list > ul'); - if (rcmail.busy) return; + var list = $('#files-folder-list > ul'); + + // try parent window if the list element does not exist + // i.e. called from dialog in parent window + if (!list.length && window.parent && parent.rcmail) { + list = $('#files-folder-list > ul', window.parent.document.body); + } + $('li.selected', list).removeClass('selected'); rcmail.enable_command('files-list', true); diff --git a/plugins/kolab_files/lib/kolab_files_engine.php b/plugins/kolab_files/lib/kolab_files_engine.php index e48ccf8f..978bef51 100644 --- a/plugins/kolab_files/lib/kolab_files_engine.php +++ b/plugins/kolab_files/lib/kolab_files_engine.php @@ -298,7 +298,7 @@ class kolab_files_engine $thead = ''; foreach ($this->file_list_head($attrib, $a_show_cols) as $cell) { - $thead .= html::tag('td', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); + $thead .= html::tag('th', array('class' => $cell['className'], 'id' => $cell['id']), $cell['html']); } return html::tag('table', $attrib, @@ -332,14 +332,21 @@ class kolab_files_engine $a_sort_cols = $this->sort_cols; if (!empty($attrib['optionsmenuicon'])) { - $onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'filelistmenu')"; - if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true') - $list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu', - 'id' => 'listmenulink', 'title' => $this->rc->gettext('listoptions'))); - else - $list_menu = html::a(array('href' => '#', 'onclick' => $onclick), - html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], - 'id' => 'listmenulink', 'title' => $this->rc->gettext('listoptions')))); + $onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'filelistmenu', this, event)"; + $inner = $this->rc->gettext('listoptions'); + + if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') { + $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions'))); + } + + $list_menu = html::a(array( + 'href' => '#list-options', + 'onclick' => $onclick, + 'class' => 'listmenu', + 'id' => 'listmenulink', + 'title' => $this->rc->gettext('listoptions'), + 'tabindex' => '0', + ), $inner); } else { $list_menu = ''; diff --git a/plugins/kolab_files/localization/en_US.inc b/plugins/kolab_files/localization/en_US.inc index 1f6e618d..b521d85f 100644 --- a/plugins/kolab_files/localization/en_US.inc +++ b/plugins/kolab_files/localization/en_US.inc @@ -1,6 +1,7 @@ $file.'; +$labels['arialabelsearchform'] = 'Files search form'; +$labels['arialabelquicksearchbox'] = 'Search input'; +$labels['arialabellistoptions'] = 'Files list options'; +$labels['arialabelfolderoptions'] = 'Folder actions'; +$labels['arialabelfileeditform'] = 'File editing form'; +$labels['arialabelfoldercreateform'] = 'Folder creation form'; +$labels['arialabelfolderlist'] = 'Folder/Collection selection'; +$labels['arialabelfileselectdialog'] = 'File selection dialog'; +$labels['arialabelattachmentoptions'] = 'Attachment save options'; +$labels['arialabelfilesavedialog'] = 'File(s) saving dialog'; +$labels['arialabelfileprops'] = 'File properties'; +$labels['arialabelfilecontent'] = 'File content'; + ?> diff --git a/plugins/kolab_files/skins/larry/style.css b/plugins/kolab_files/skins/larry/style.css index d566a100..e75a5bbd 100644 --- a/plugins/kolab_files/skins/larry/style.css +++ b/plugins/kolab_files/skins/larry/style.css @@ -53,7 +53,9 @@ } #filestoolbar a.button.print { - background: url(../../../../skins/larry/images/buttons.png) center -810px no-repeat; + background-image: url(../../../../skins/larry/images/buttons.png); + background-position: center -810px; + background-repeat: no-repeat; } #filestoolbar form { @@ -152,7 +154,7 @@ color: #aaa; } -.filelist thead tr td { +.filelist thead tr th { padding: 0; } @@ -161,50 +163,52 @@ height: 18px; } -.filelist tr td.size { +.filelist tr > .size { width: 80px; text-align: right; } -.filelist thead tr td.size { +.filelist thead tr > .size { text-align: left; } -.filelist tr td.mtime { +.filelist tr > .mtime { width: 125px; } -.filelist tr td.options { - width: 26px; +.filelist tr > .options { + width: 32px; cursor: pointer; } -.filelist thead tr td.filename, +.filelist thead tr th.filename, .filelist tbody tr td.filename { width: 99%; white-space: nowrap; } -.filelist thead tr td.sortedASC a, -.filelist thead tr td.sortedDESC a { +.filelist thead tr th.sortedASC a, +.filelist thead tr th.sortedDESC a { color: #004458; text-decoration: underline; - background: url(../../../../skins/larry/images/listicons.png) right -912px no-repeat; + background-image: url(../../../../skins/larry/images/listicons.png); + background-position: right -912px; + background-repeat: no-repeat; } -.filelist thead tr td.sortedASC a { +.filelist thead tr th.sortedASC a { background-position: right -944px; } -.filelist td img { +.filelist img { vertical-align: middle; display: inline-block; } -.filelist tr td.options div.listmenu, -.filelist tr td.flag span.flagged, -.filelist tr td.flag span.unflagged, -.filelist tr td.flag span.unflagged:hover { +.filelist tr > .options a.listmenu, +.filelist tr > .flag span.flagged, +.filelist tr > .flag span.unflagged, +.filelist tr > .flag span.unflagged:hover { display: inline-block; vertical-align: middle; height: 18px; @@ -213,21 +217,26 @@ background: url(../../../../skins/larry/images/listicons.png) -100px 0 no-repeat; } -.filelist thead tr td.options div.listmenu { - background-position: 0 -976px; +.filelist thead tr th.options { + padding: 0; + border-left: none; +} + +.filelist thead tr th.options .listmenu { + background-position: 3px -970px; cursor: pointer; - width: 26px; + width: 24px; + height: 20px; + padding: 4px 4px 5px; + text-indent: -5000px; } -.filelist thead tr td.options { - padding: 0 3px; +.filelist thead tr th.options .listmenu:focus { + outline: none; + background-color: rgba(73,180,210,0.7); } -.filelist thead tr td.options { - padding: 2px 3px; -} - -.filelist thead tr td:first-child { +.filelist thead tr th:first-child { border-radius: 4px 0 0 0; } diff --git a/plugins/kolab_files/skins/larry/templates/compose_plugin.html b/plugins/kolab_files/skins/larry/templates/compose_plugin.html index 2c458692..613a24a4 100644 --- a/plugins/kolab_files/skins/larry/templates/compose_plugin.html +++ b/plugins/kolab_files/skins/larry/templates/compose_plugin.html @@ -1,21 +1,27 @@ -
    -