Files: Accessibility improvements (#3087), Display dialogs from frames in main window.

This commit is contained in:
Aleksander Machniak 2014-06-12 12:55:34 +02:00
parent 6d1ffc345d
commit d1e3acf1ad
9 changed files with 268 additions and 120 deletions

View file

@ -30,22 +30,21 @@ window.rcmail && rcmail.addEventListener('init', function() {
// mail compose // mail compose
if (rcmail.env.action == 'compose') { if (rcmail.env.action == 'compose') {
var elem = $('#compose-attachments > div'), var elem = $('#compose-attachments > div'),
input = $('<input class="button" type="button">'); input = $('<input class="button" type="button">')
.attr('tabindex', $('input', elem).attr('tabindex') || 0)
input.val(rcmail.gettext('kolab_files.fromcloud')) .val(rcmail.gettext('kolab_files.fromcloud'))
.click(function() { kolab_files_selector_dialog(); }) .click(function() { kolab_files_selector_dialog(); })
.appendTo(elem); .appendTo(elem);
if (rcmail.gui_objects.filelist) { if (rcmail.gui_objects.filelist) {
rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, { rcmail.file_list = new rcube_list_widget(rcmail.gui_objects.filelist, {
multiselect: true, multiselect: true,
// draggable: true,
keyboard: true, keyboard: true,
column_movable: false, column_movable: false,
dblclick_time: rcmail.dblclick_time dblclick_time: rcmail.dblclick_time
}); });
rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); }); rcmail.file_list.addEventListener('select', function(o) { kolab_files_list_select(o); })
rcmail.file_list.addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', e); }); .addEventListener('listupdate', function(e) { rcmail.triggerEvent('listupdate', 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('files-sort', 'files-search', 'files-search-reset', true); 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('dragstart', function(o){ p.drag_start(o); });
rcmail.file_list.addEventListener('dragmove', function(e){ p.drag_move(e); }); 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('dblclick', function(o) { kolab_files_list_dblclick(o); })
rcmail.file_list.addEventListener('select', function(o){ kolab_files_list_select(o); }); .addEventListener('select', function(o) { kolab_files_list_select(o); })
rcmail.file_list.addEventListener('dragend', function(e){ kolab_files_drag_end(e); }); .addEventListener('keypress', function(o) { kolab_files_list_keypress(o); })
rcmail.file_list.addEventListener('column_replace', function(e){ kolab_files_set_coltypes(e); }); .addEventListener('dragend', function(e) { kolab_files_drag_end(e); })
rcmail.file_list.addEventListener('listupdate', function(e){ rcmail.triggerEvent('listupdate', 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(); rcmail.file_list.init();
kolab_files_list_coltypes(); 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 // consider the token from parent window more reliable (fresher) than in framed window
// it's because keep-alive is not requested in frames // 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 // folder selection dialog
@ -164,11 +163,20 @@ function kolab_directory_selector_dialog(id)
input = $('#file-save-as-input'), input = $('#file-save-as-input'),
form = $('#file-save-as'), form = $('#file-save-as'),
list = $('#folderlistbox'), list = $('#folderlistbox'),
buttons = {}, label = 'saveto'; buttons = {}, label = 'saveto',
win = window, fn;
// attachment is specified // attachment is specified
if (id) { 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(); form.show();
dialog.addClass('saveas'); dialog.addClass('saveas');
input.val(filename); input.val(filename);
@ -186,6 +194,8 @@ function kolab_directory_selector_dialog(id)
label = 'saveall'; label = 'saveall';
} }
$('#foldercreatelink').attr('tabindex', 0);
buttons[rcmail.gettext('kolab_files.save')] = function () { buttons[rcmail.gettext('kolab_files.save')] = function () {
var lock = rcmail.set_busy(true, 'saving'), var lock = rcmail.set_busy(true, 'saving'),
request = { request = {
@ -201,12 +211,20 @@ function kolab_directory_selector_dialog(id)
} }
rcmail.http_post('plugin.kolab_files', request, lock); rcmail.http_post('plugin.kolab_files', request, lock);
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
buttons[rcmail.gettext('kolab_files.cancel')] = function () { 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 // show dialog window
kolab_dialog_show(dialog, { kolab_dialog_show(dialog, {
title: rcmail.gettext('kolab_files.' + label), title: rcmail.gettext('kolab_files.' + label),
@ -215,11 +233,14 @@ function kolab_directory_selector_dialog(id)
minHeight: 300, minHeight: 300,
height: 350, height: 350,
width: 300 width: 300
}); }, fn);
if (!rcmail.env.folders_loaded) { // "enable" folder creation when dialog is displayed in parent window
file_api.folder_list(); if (rcmail.is_framed() && !parent.rcmail.folder_create) {
rcmail.env.folders_loaded = true; 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')); list.push($(this).data('file'));
}); });
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
if (list.length) { if (list.length) {
// display upload indicator and cancel button // display upload indicator and cancel button
@ -252,8 +273,9 @@ function kolab_files_selector_dialog()
}); });
} }
}; };
buttons[rcmail.gettext('kolab_files.cancel')] = function () { buttons[rcmail.gettext('kolab_files.cancel')] = function () {
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
// show dialog window // show dialog window
@ -270,8 +292,9 @@ function kolab_files_selector_dialog()
file_api.folder_list(); file_api.folder_list();
rcmail.env.files_loaded = true; rcmail.env.files_loaded = true;
} }
else else {
rcmail.file_list.clear_selection(); rcmail.file_list.clear_selection();
}
}; };
function kolab_files_attach_menu_open(p) function kolab_files_attach_menu_open(p)
@ -306,10 +329,11 @@ function kolab_files_folder_create_dialog()
folder += name; folder += name;
file_api.folder_create(folder); file_api.folder_create(folder);
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
buttons[rcmail.gettext('kolab_files.cancel')] = function () { buttons[rcmail.gettext('kolab_files.cancel')] = function () {
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
// show dialog window // show dialog window
@ -358,10 +382,10 @@ function kolab_files_file_edit_dialog(file)
// @TODO: now we only update filename // @TODO: now we only update filename
if (name != file) if (name != file)
file_api.file_rename(file, name); file_api.file_rename(file, name);
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
buttons[rcmail.gettext('kolab_files.cancel')] = function () { buttons[rcmail.gettext('kolab_files.cancel')] = function () {
dialog.dialog('destroy').hide(); kolab_dialog_close(this);
}; };
// Fix submitting form with Enter // 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({ params = $.extend({
modal: true, modal: true,
resizable: !bw.ie6, resizable: true,
closeOnEscape: (!bw.ie6 && !bw.ie7), // disabled for performance reasons closeOnEscape: (!bw.ie6 && !bw.ie7), // disabled for performance reasons
minWidth: 400, minWidth: 400,
minHeight: 300, minHeight: 300,
@ -386,7 +410,36 @@ function kolab_dialog_show(dialog, params)
height: 400 height: 400
}, params || {}); }, 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 // Handle form submit with Enter key, click first dialog button instead
@ -396,6 +449,12 @@ function kolab_dialog_submit_handler()
return false; return false;
}; };
// Hides dialog
function kolab_dialog_close(dialog)
{
(rcmail.is_framed() ? window.parent : window).$(dialog).dialog('close');
};
// smart upload button // smart upload button
function kolab_files_upload_input(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.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'); }) .change(function() { rcmail.files_upload('#filesuploadform'); })
.click(function() { setTimeout(function() { link.mouseleave(); }, 20); }) .click(function() { setTimeout(function() { link.mouseleave(); }, 20); })
// opacity:0 does the trick, display/visibility doesn't work // 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); 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) kolab_files_drag_end = function(e)
{ {
var folder = $('#files-folder-list li.droptarget').removeClass('droptarget'); 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); this.set_quota(p);
}; };
rcube_webmail.prototype.folder_create = function()
{
kolab_files_folder_create_dialog();
};
/**********************************************************/ /**********************************************************/
/********* Files API handler **********/ /********* Files API handler **********/
@ -850,6 +925,12 @@ function kolab_files_ui()
list = $('<ul class="listing"></ul>'), list = $('<ul class="listing"></ul>'),
collections = !rcmail.env.action.match(/^(preview|show)$/) ? ['audio', 'video', 'image', 'document'] : []; 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); elem.html('').append(list);
this.env.folders = this.folder_list_parse(response.result); this.env.folders = this.folder_list_parse(response.result);
@ -868,7 +949,9 @@ function kolab_files_ui()
if (f.virtual) if (f.virtual)
row.addClass('virtual'); row.addClass('virtual');
else 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() { .mouseenter(function() {
if (rcmail.file_list && rcmail.file_list.drag_active && !$(this).hasClass('selected')) if (rcmail.file_list && rcmail.file_list.drag_active && !$(this).hasClass('selected'))
$(this).addClass('droptarget'); $(this).addClass('droptarget');
@ -888,7 +971,7 @@ function kolab_files_ui()
$.each(collections, function(i, n) { $.each(collections, function(i, n) {
var row = $('<li class="mailbox collection ' + n + '"></li>'); var row = $('<li class="mailbox collection ' + n + '"></li>');
row.attr('id', 'folder-collection-' + n) row.attr({id: 'folder-collection-' + n, tabindex: 0})
.append($('<span class="name"></span>').text(rcmail.gettext('kolab_files.collection_' + n))) .append($('<span class="name"></span>').text(rcmail.gettext('kolab_files.collection_' + n)))
.click(function() { file_api.folder_select(n, true); }); .click(function() { file_api.folder_select(n, true); });
@ -909,11 +992,17 @@ function kolab_files_ui()
this.folder_select = function(folder, is_collection) this.folder_select = function(folder, is_collection)
{ {
var list = $('#files-folder-list > ul');
if (rcmail.busy) if (rcmail.busy)
return; 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'); $('li.selected', list).removeClass('selected');
rcmail.enable_command('files-list', true); rcmail.enable_command('files-list', true);

View file

@ -298,7 +298,7 @@ class kolab_files_engine
$thead = ''; $thead = '';
foreach ($this->file_list_head($attrib, $a_show_cols) as $cell) { 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, return html::tag('table', $attrib,
@ -332,14 +332,21 @@ class kolab_files_engine
$a_sort_cols = $this->sort_cols; $a_sort_cols = $this->sort_cols;
if (!empty($attrib['optionsmenuicon'])) { if (!empty($attrib['optionsmenuicon'])) {
$onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'filelistmenu')"; $onclick = 'return ' . JS_OBJECT_NAME . ".command('menu-open', 'filelistmenu', this, event)";
if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true') $inner = $this->rc->gettext('listoptions');
$list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu',
'id' => 'listmenulink', 'title' => $this->rc->gettext('listoptions'))); if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') {
else $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions')));
$list_menu = html::a(array('href' => '#', 'onclick' => $onclick), }
html::img(array('src' => $skin_path . $attrib['optionsmenuicon'],
'id' => 'listmenulink', 'title' => $this->rc->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 { else {
$list_menu = ''; $list_menu = '';

View file

@ -1,6 +1,7 @@
<?php <?php
$labels['files'] = 'Files'; $labels['files'] = 'Files';
$labels['filepreview'] = 'File preview';
$labels['saveall'] = 'Save all to cloud...'; $labels['saveall'] = 'Save all to cloud...';
$labels['saveto'] = 'Save to cloud...'; $labels['saveto'] = 'Save to cloud...';
$labels['saveas'] = 'Save as:'; $labels['saveas'] = 'Save as:';
@ -67,4 +68,17 @@ $labels['fileoverwrite'] = 'Overwrite';
$labels['fileoverwriteall'] = 'Overwrite all'; $labels['fileoverwriteall'] = 'Overwrite all';
$labels['filemoveconfirm'] = 'This action is going to overwrite the destination file: <b>$file</b>.'; $labels['filemoveconfirm'] = 'This action is going to overwrite the destination file: <b>$file</b>.';
$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';
?> ?>

View file

@ -53,7 +53,9 @@
} }
#filestoolbar a.button.print { #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 { #filestoolbar form {
@ -152,7 +154,7 @@
color: #aaa; color: #aaa;
} }
.filelist thead tr td { .filelist thead tr th {
padding: 0; padding: 0;
} }
@ -161,50 +163,52 @@
height: 18px; height: 18px;
} }
.filelist tr td.size { .filelist tr > .size {
width: 80px; width: 80px;
text-align: right; text-align: right;
} }
.filelist thead tr td.size { .filelist thead tr > .size {
text-align: left; text-align: left;
} }
.filelist tr td.mtime { .filelist tr > .mtime {
width: 125px; width: 125px;
} }
.filelist tr td.options { .filelist tr > .options {
width: 26px; width: 32px;
cursor: pointer; cursor: pointer;
} }
.filelist thead tr td.filename, .filelist thead tr th.filename,
.filelist tbody tr td.filename { .filelist tbody tr td.filename {
width: 99%; width: 99%;
white-space: nowrap; white-space: nowrap;
} }
.filelist thead tr td.sortedASC a, .filelist thead tr th.sortedASC a,
.filelist thead tr td.sortedDESC a { .filelist thead tr th.sortedDESC a {
color: #004458; color: #004458;
text-decoration: underline; 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; background-position: right -944px;
} }
.filelist td img { .filelist img {
vertical-align: middle; vertical-align: middle;
display: inline-block; display: inline-block;
} }
.filelist tr td.options div.listmenu, .filelist tr > .options a.listmenu,
.filelist tr td.flag span.flagged, .filelist tr > .flag span.flagged,
.filelist tr td.flag span.unflagged, .filelist tr > .flag span.unflagged,
.filelist tr td.flag span.unflagged:hover { .filelist tr > .flag span.unflagged:hover {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
height: 18px; height: 18px;
@ -213,21 +217,26 @@
background: url(../../../../skins/larry/images/listicons.png) -100px 0 no-repeat; background: url(../../../../skins/larry/images/listicons.png) -100px 0 no-repeat;
} }
.filelist thead tr td.options div.listmenu { .filelist thead tr th.options {
background-position: 0 -976px; padding: 0;
border-left: none;
}
.filelist thead tr th.options .listmenu {
background-position: 3px -970px;
cursor: pointer; cursor: pointer;
width: 26px; width: 24px;
height: 20px;
padding: 4px 4px 5px;
text-indent: -5000px;
} }
.filelist thead tr td.options { .filelist thead tr th.options .listmenu:focus {
padding: 0 3px; outline: none;
background-color: rgba(73,180,210,0.7);
} }
.filelist thead tr td.options { .filelist thead tr th:first-child {
padding: 2px 3px;
}
.filelist thead tr td:first-child {
border-radius: 4px 0 0 0; border-radius: 4px 0 0 0;
} }

View file

@ -1,21 +1,27 @@
<div id="files-compose-dialog" class="uidialog"> <div id="files-compose-dialog" class="uidialog" role="dialog" aria-labelledby="aria-label-fileselect" aria-hidden="true">
<div id="quicksearchbar" class="searchbox"> <h2 id="aria-label-fileselect" class="voice"><roundcube:label name="kolab_files.arialabelfileselectdialog" /></h2>
<div id="quicksearchbar" class="searchbox" role="search" aria-labelledby="aria-label-searchform">
<h3 id="aria-label-searchform" class="voice"><roundcube:label name="kolab_files.arialabelsearchform" /></h3>
<label for="quicksearchbox" class="voice"><roundcube:label name="arialabelquicksearchbox" /></label>
<roundcube:button name="filesearchmenulink" id="filesearchmenulink" class="iconbutton searchoptions" onclick="return UI.toggle_popup('filesearchmenu', event)" title="searchmod" label="options" aria-haspopup="true" aria-expanded="false" aria-owns="filesearchmenu-menu" />
<roundcube:object name="file-search-form" id="filesearchbox" /> <roundcube:object name="file-search-form" id="filesearchbox" />
<roundcube:button name="filesearchmenulink" id="filesearchmenulink" class="iconbutton searchoptions" onclick="UI.show_popup('filesearchmenu');return false" title="searchmod" content=" " />
<roundcube:button command="files-search-reset" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " /> <roundcube:button command="files-search-reset" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
</div> </div>
<div id="folderlistbox" class="uibox listbox"> <div id="folderlistbox" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h3 id="aria-label-folderlist" class="voice"><roundcube:label name="kolab_files.arialabelfolderlist" /></h3>
<div id="files-folder-list" class="scroller"></div> <div id="files-folder-list" class="scroller"></div>
</div> </div>
<div id="filelistcontainer" class="boxlistcontent uibox"> <div id="filelistcontainer" class="boxlistcontent uibox">
<roundcube:object name="filelist" id="filelist" class="records-table filelist sortheader fixedheader" /> <h3 id="aria-label-filelist" class="voice"><roundcube:label name="arialabelfilelist" /></h3>
<roundcube:object name="filelist" id="filelist" class="records-table filelist sortheader fixedheader" aria-labelledby="aria-label-filelist" />
</div> </div>
</div> </div>
<div id="filesearchmenu" class="popupmenu" style="z-index: 2000"> <div id="filesearchmenu" class="popupmenu" style="z-index: 2000" data-editable="true" aria-hidden="true">
<ul class="toolbarmenu"> <h4 id="aria-label-searchmenu" class="voice"><roundcube:label name="searchmod" /></h4>
<li><label><input type="checkbox" name="all_folders" value="1" id="search_all_folders" /> <span><roundcube:label name="kolab_files.allfolders" /></span></label></li> <ul id="filesearchmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-searchmenu">
<li role="menuitem"><label><input type="checkbox" name="all_folders" value="1" id="search_all_folders" /> <span><roundcube:label name="kolab_files.allfolders" /></span></label></li>
</ul> </ul>
</div> </div>

View file

@ -9,10 +9,12 @@
<roundcube:include file="/includes/header.html" /> <roundcube:include file="/includes/header.html" />
<div id="mainscreen"> <div id="mainscreen">
<div id="filestoolbar" class="toolbar"> <h1 class="voice"><roundcube:label name="kolab_files.filepreview" /></h1>
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div id="filestoolbar" class="toolbar" role="toolbar" aria-labelledby="aria-label-toolbar">
<roundcube:button command="files-get" type="link" class="button get disabled" classAct="button get" classSel="button get pressed" label="kolab_files.get" title="kolab_files.getfile" /> <roundcube:button command="files-get" type="link" class="button get disabled" classAct="button get" classSel="button get pressed" label="kolab_files.get" title="kolab_files.getfile" />
<roundcube:button command="files-edit" type="link" class="button edit disabled" classAct="button edit" classSel="button edit pressed" label="kolab_files.edit" title="kolab_files.editfile" /> <roundcube:button command="files-edit" type="link" class="button edit disabled" classAct="button edit" classSel="button edit pressed" label="kolab_files.edit" title="kolab_files.editfile" />
<roundcube:button command="files-save" type="link" class="button save disabled" classAct="button save" classSel="button save pressed" label="kolab_files.save" title="kolab_files.savefile" style="display:none" /> <roundcube:button command="files-save" type="link" class="button save disabled" classAct="button save" classSel="button save pressed" label="kolab_files.save" title="kolab_files.savefile" style="display:none" />
@ -20,13 +22,14 @@
<roundcube:button command="files-print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" title="kolab_files.printfile" /> <roundcube:button command="files-print" type="link" class="button print disabled" classAct="button print" classSel="button print pressed" label="print" title="kolab_files.printfile" />
</div> </div>
<div id="fileinfobox" class="uibox listbox"> <h2 id="aria-label-fileprops" class="voice"><roundcube:label name="kolab_files.arialabelfileprops" /></h2>
<div id="fileinfobox" class="uibox listbox" aria-labelledby="aria-label-toolbar">
<roundcube:object name="fileinfobox" id="fileinfo" class="listing" /> <roundcube:object name="fileinfobox" id="fileinfo" class="listing" />
</div> </div>
<div id="filecontent" class="uibox"> <div id="filecontent" class="uibox">
<div class="iframebox"> <div class="iframebox">
<roundcube:object name="filepreviewframe" id="fileframe" frameborder="0" /> <roundcube:object name="filepreviewframe" id="fileframe" frameborder="0" title="kolab_files.arialabelfilecontent" />
</div> </div>
</div> </div>

View file

@ -11,7 +11,10 @@
<div id="mainscreen"> <div id="mainscreen">
<div id="filestoolbar" class="toolbar"> <h1 class="voice"><roundcube:label name="kolab_files.files" /></h1>
<div id="filestoolbar" class="toolbar" role="toolbar" aria-labelledby="aria-label-toolbar">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<form id="filesuploadform"> <form id="filesuploadform">
<roundcube:button command="files-upload" type="link" class="button upload disabled" classAct="button upload" classSel="button upload pressed" label="kolab_files.upload" title="kolab_files.uploadfile" /> <roundcube:button command="files-upload" type="link" class="button upload disabled" classAct="button upload" classSel="button upload pressed" label="kolab_files.upload" title="kolab_files.uploadfile" />
</form> </form>
@ -20,50 +23,59 @@
<roundcube:button command="files-delete" type="link" class="button delete disabled" classAct="button delete" classSel="button delete pressed" label="delete" title="kolab_files.deletefile" /> <roundcube:button command="files-delete" type="link" class="button delete disabled" classAct="button delete" classSel="button delete pressed" label="delete" title="kolab_files.deletefile" />
</div> </div>
<div id="quicksearchbar" class="quicksearchbox"> <div id="quicksearchbar" class="quicksearchbox" role="search" aria-labelledby="aria-label-searchform">
<h2 id="aria-label-searchform" class="voice"><roundcube:label name="kolab_files.arialabelsearchform" /></h2>
<label for="quicksearchbox" class="voice"><roundcube:label name="arialabelquicksearchbox" /></label>
<roundcube:button name="filesearchmenulink" id="filesearchmenulink" class="iconbutton searchoptions" onclick="return UI.toggle_popup('filesearchmenu', event)" title="searchmod" label="options" aria-haspopup="true" aria-expanded="false" aria-owns="filesearchmenu-menu" />
<roundcube:object name="file-search-form" id="quicksearchbox" /> <roundcube:object name="file-search-form" id="quicksearchbox" />
<roundcube:button name="filesearchmenulink" id="filesearchmenulink" class="iconbutton searchoptions" onclick="UI.show_popup('filesearchmenu');return false" title="searchmod" content=" " /> <roundcube:button command="files-search-reset" id="searchreset" class="iconbutton reset" title="resetsearch" label="resetsearch" />
<roundcube:button command="files-search-reset" id="searchreset" class="iconbutton reset" title="resetsearch" content=" " />
</div> </div>
<div id="folderlistbox" class="uibox listbox"> <div id="folderlistbox" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="kolab_files.arialabelfolderlist" /></h2>
<div id="files-folder-list" class="scroller withfooter"> <div id="files-folder-list" class="scroller withfooter">
</div> </div>
<div id="folderlist-footer" class="boxfooter"> <div id="folderlist-footer" class="boxfooter">
<roundcube:button name="folder-create" type="link" title="kolab_files.foldercreate" class="listbutton add" classAct="listbutton add" innerClass="inner" content="+" onclick="kolab_files_folder_create_dialog()" /><roundcube:button name="folderoptions" id="folderoptionslink" type="link" title="moreactions" class="listbutton groupactions" onclick="UI.show_popup('folderoptions', undefined, {above: 1});return false" innerClass="inner" content="&#9881;" /> <roundcube:button command="folder-create" type="link" title="kolab_files.foldercreate" class="listbutton add" classAct="listbutton add" innerClass="inner" content="+" /><roundcube:button name="folderoptions" id="folderoptionslink" type="link" title="moreactions" class="listbutton groupactions" onclick="return UI.toggle_popup('folderoptions', event)" innerClass="inner" content="&#9881;" aria-haspopup="true" aria-expanded="false" aria-owns="folderoptionsmenu" />
<roundcube:if condition="env:files_quota" /> <roundcube:if condition="env:files_quota" />
<span class="voice"><roundcube:label name="quota"></span>
<roundcube:object name="filequotadisplay" id="quotadisplay" class="countdisplay" display="text" /> <roundcube:object name="filequotadisplay" id="quotadisplay" class="countdisplay" display="text" />
<roundcube:endif /> <roundcube:endif />
</div> </div>
</div> </div>
<div id="filelistcontainer" class="uibox"> <div id="filelistcontainer" class="uibox">
<h2 id="aria-label-filelist" class="voice"><roundcube:label name="arialabelfilelist" /></h2>
<div id="filelistbox" class="boxlistcontent"> <div id="filelistbox" class="boxlistcontent">
<roundcube:object name="filelist" id="filelist" class="records-table filelist sortheader fixedheader" optionsmenuIcon="true" /> <roundcube:object name="filelist" id="filelist" class="records-table filelist sortheader fixedheader" optionsmenuIcon="true" aria-labelledby="aria-label-filelist" />
</div> </div>
</div> </div>
</div> </div>
<div id="folderoptions" class="popupmenu"> <div id="folderoptions" class="popupmenu" data-editable="true" aria-hidden="true">
<ul id="folderoptionsmenu" class="toolbarmenu"> <h3 id="aria-label-folderoptions" class="voice"><roundcube:label name="kolab_files.folderoptions" /></h3>
<ul id="folderoptionsmenu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-folderoptions">
<!-- <!--
<li><roundcube:button command="files-folder-edit" label="edit" classAct="active" /></li> <li role="menuitem"><roundcube:button command="files-folder-edit" label="edit" classAct="active" /></li>
--> -->
<li><roundcube:button command="files-folder-delete" label="delete" classAct="active" /></li> <li role="menuitem"><roundcube:button command="files-folder-delete" label="delete" classAct="active" /></li>
<li><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li> <li role="menuitem"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
<roundcube:container name="filesfolderoptions" id="folderoptionsmenu" /> <roundcube:container name="filesfolderoptions" id="folderoptionsmenu" />
</ul> </ul>
</div> </div>
<div id="files-folder-create-dialog"> <div id="files-folder-create-dialog" role="dialog" aria-labelledby="aria-label-foldercreateform" aria-hidden="true">
<h3 id="aria-label-foldercreateform" class="voice"><roundcube:label name="kolab_files.arialabelfoldercreateform" /></h3>
<roundcube:object name="folder-create-form" /> <roundcube:object name="folder-create-form" />
</div> </div>
<div id="files-file-edit-dialog"> <div id="files-file-edit-dialog" role="dialog" aria-labelledby="aria-label-fileeditform" aria-hidden="true">
<h3 id="aria-label-fileeditform" class="voice"><roundcube:label name="kolab_files.arialabelfileeditform" /></h3>
<roundcube:object name="file-edit-form" /> <roundcube:object name="file-edit-form" />
</div> </div>
<div id="listoptions" class="propform popupdialog"> <div id="listoptions" class="propform popupdialog" data-editable="true" role="dialog" aria-labelledby="aria-label-listoptions" aria-hidden="true">
<h3 id="aria-label-listoptions" class="voice"><roundcube:label name="kolab_files.arialabellistoptions" /></h3>
<roundcube:if condition="!in_array('kolab_files_list_cols', (array)config:dont_override)" /> <roundcube:if condition="!in_array('kolab_files_list_cols', (array)config:dont_override)" />
<fieldset class="floating"> <fieldset class="floating">
<legend><roundcube:label name="listcolumns" /></legend> <legend><roundcube:label name="listcolumns" /></legend>
@ -97,20 +109,21 @@
<br style="clear:both" /> <br style="clear:both" />
<div class="formbuttons"> <div class="formbuttons">
<roundcube:button command="menu-save" id="listmenusave" type="input" class="button mainaction" label="save" /> <roundcube:button command="menu-save" id="listmenusave" type="input" class="button mainaction" label="save" />
<roundcube:button command="menu-open" id="listmenucancel" type="input" class="button" label="cancel" /> <roundcube:button command="menu-close" prop="filelistmenu" id="listmenucancel" type="input" class="button" label="cancel" />
</div> </div>
</div> </div>
<div id="dragfilemenu" class="popupmenu"> <div id="dragfilemenu" class="popupmenu" aria-hidden="true">
<ul class="toolbarmenu"> <ul class="toolbarmenu" role="menu">
<li><roundcube:button command="files-move" onclick="return kolab_files_drag_menu_action('files-move')" label="move" classAct="active" /></li> <li role="menuitem"><roundcube:button command="files-move" onclick="return kolab_files_drag_menu_action('files-move')" label="move" classAct="active" /></li>
<li><roundcube:button command="files-copy" onclick="return kolab_files_drag_menu_action('files-copy')" label="copy" classAct="active" /></li> <li role="menuitem"><roundcube:button command="files-copy" onclick="return kolab_files_drag_menu_action('files-copy')" label="copy" classAct="active" /></li>
</ul> </ul>
</div> </div>
<div id="filesearchmenu" class="popupmenu"> <div id="filesearchmenu" class="popupmenu" data-editable="true" aria-hidden="true">
<ul class="toolbarmenu"> <h3 id="aria-label-searchmenu" class="voice"><roundcube:label name="searchmod" /></h3>
<li><label><input type="checkbox" name="all_folders" value="1" id="search_all_folders" /> <span><roundcube:label name="kolab_files.allfolders" /></span></label></li> <ul id="filesearchmenu-menu" class="toolbarmenu" role="menu" aria-labelledby="aria-label-searchmenu">
<li role="menuitem"><label><input type="checkbox" name="all_folders" value="1" id="search_all_folders" /> <span><roundcube:label name="kolab_files.allfolders" /></span></label></li>
</ul> </ul>
</div> </div>

View file

@ -1,16 +1,21 @@
<div id="files-dialog" class="uidialog"> <div id="files-dialog" class="uidialog" data-editable="true" role="dialog" aria-labelledby="aria-label-filesavedialog" aria-hidden="true">
<h3 id="aria-label-filesavedialog" class="voice"><roundcube:label name="kolab_files.arialabelfilesavedialog" /></h3>
<div id="file-save-as"> <div id="file-save-as">
<label for="file-save-as-input"><roundcube:label name="kolab_files.saveas" /></label> <label for="file-save-as-input"><roundcube:label name="kolab_files.saveas" /></label>
<input id="file-save-as-input" type="text" value=""> <input id="file-save-as-input" type="text" value="">
</div> </div>
<div id="folderlistbox" class="uibox listbox"> <div id="folderlistbox" class="uibox listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<h3 id="aria-label-folderlist" class="voice"><roundcube:label name="kolab_files.arialabelfolderlist" /></h3>
<div id="files-folder-list" class="scroller withfooter"></div> <div id="files-folder-list" class="scroller withfooter"></div>
<div id="folderlist-footer" class="boxfooter"> <div id="folderlist-footer" class="boxfooter">
<roundcube:button name="foldercreatelink" id="foldercreatelink" type="link" onclick="kolab_files_folder_create_dialog()" title="createfolder" class="listbutton add" classAct="listbutton add" innerClass="inner" content="+" /> <roundcube:button command="folder-create" name="foldercreatelink" id="foldercreatelink" type="link" title="createfolder" class="listbutton add" classAct="listbutton add" innerClass="inner" content="+" />
</div> </div>
</div> </div>
</div> </div>
<div id="files-folder-create-dialog">
<div id="files-folder-create-dialog" role="dialog" aria-labelledby="aria-label-foldercreateform" aria-hidden="true">
<h3 id="aria-label-foldercreateform" class="voice"><roundcube:label name="kolab_files.arialabelfoldercreateform" /></h3>
<roundcube:object name="folder-create-form" /> <roundcube:object name="folder-create-form" />
</div> </div>
<script src="plugins/kolab_files/skins/larry/ui.js" type="text/javascript"></script> <script src="plugins/kolab_files/skins/larry/ui.js" type="text/javascript"></script>

View file

@ -13,6 +13,7 @@ function kolab_files_ui_init()
$(document).ready(function() { $(document).ready(function() {
rcmail.addEventListener('menu-open', kolab_files_show_listoptions); rcmail.addEventListener('menu-open', kolab_files_show_listoptions);
rcmail.addEventListener('menu-save', kolab_files_save_listoptions); rcmail.addEventListener('menu-save', kolab_files_save_listoptions);
rcmail.addEventListener('menu-close', kolab_files_show_listoptions);
rcmail.addEventListener('setquota', kolab_files_update_quota); rcmail.addEventListener('setquota', kolab_files_update_quota);
var menu = $('#dragfilemenu'); var menu = $('#dragfilemenu');
@ -24,7 +25,6 @@ function kolab_files_ui_init()
menu = $('#filesearchmenu'); menu = $('#filesearchmenu');
if (menu.length) { if (menu.length) {
rcmail.gui_object('file_searchmenu', 'filesearchmenu'); rcmail.gui_object('file_searchmenu', 'filesearchmenu');
UI.add_popup('filesearchmenu', {sticky: 1});
} }
}); });
@ -45,8 +45,12 @@ function kolab_files_update_quota(p)
return UI.update_quota(p); return UI.update_quota(p);
}; };
function kolab_files_show_listoptions() function kolab_files_show_listoptions(p)
{ {
if (!p || p.name != 'filelistmenu') {
return;
}
var $dialog = $('#listoptions'); var $dialog = $('#listoptions');
// close the dialog // close the dialog
@ -69,10 +73,8 @@ function kolab_files_show_listoptions()
modal: true, modal: true,
resizable: false, resizable: false,
closeOnEscape: true, closeOnEscape: true,
close: function() { rcmail.file_list.focus(); },
title: null, title: null,
close: function() {
$dialog.dialog('destroy').hide();
},
minWidth: 400, minWidth: 400,
width: $dialog.width()+20 width: $dialog.width()+20
}).show(); }).show();