Finalize accessibility improvements for the notes module (#3088)

This commit is contained in:
Thomas Bruederli 2014-06-20 17:02:51 +02:00
parent 982b673d37
commit e26c4836bc
5 changed files with 94 additions and 59 deletions

View file

@ -135,8 +135,9 @@ class kolab_notes_ui
if ($prop['class_name']) if ($prop['class_name'])
$class .= ' '.$prop['class_name']; $class .= ' '.$prop['class_name'];
$attr = $prop['virtual'] ? array('tabindex' => '0') : array('href' => $this->rc->url(array('_list' => $id)));
$items .= html::tag('li', array('id' => 'rcmliknb' . $html_id, 'class' => trim($class)), $items .= html::tag('li', array('id' => 'rcmliknb' . $html_id, 'class' => trim($class)),
html::span(array('class' => 'listname', 'title' => $title), $prop['listname']) . html::a($attr + array('class' => 'listname', 'title' => $title), $prop['listname']) .
html::span(array('class' => 'count'), '') html::span(array('class' => 'count'), '')
); );
} }
@ -169,7 +170,7 @@ class kolab_notes_ui
$this->rc->output->add_gui_object('noteseditform', $attrib['id']); $this->rc->output->add_gui_object('noteseditform', $attrib['id']);
$this->rc->output->include_script('tinymce/tinymce.min.js'); $this->rc->output->include_script('tinymce/tinymce.min.js');
$textarea = new html_textarea(array('name' => 'content', 'id' => 'notecontent', 'cols' => 60, 'rows' => 20, 'tabindex' => 3)); $textarea = new html_textarea(array('name' => 'content', 'id' => 'notecontent', 'cols' => 60, 'rows' => 20, 'tabindex' => 0));
return html::tag('form', $attrib, $textarea->show(), array_merge(html::$common_attrib, array('action'))); return html::tag('form', $attrib, $textarea->show(), array_merge(html::$common_attrib, array('action')));
} }
@ -185,7 +186,7 @@ class kolab_notes_ui
$attrib += array('id' => 'rcmkolabnotestitle'); $attrib += array('id' => 'rcmkolabnotestitle');
$this->rc->output->add_gui_object('noteviewtitle', $attrib['id']); $this->rc->output->add_gui_object('noteviewtitle', $attrib['id']);
$summary = new html_inputfield(array('name' => 'summary', 'class' => 'notetitle inline-edit', 'size' => 60, 'tabindex' => 1)); $summary = new html_inputfield(array('name' => 'summary', 'class' => 'notetitle inline-edit', 'size' => 60, 'tabindex' => 0));
$html = $summary->show(); $html = $summary->show();
$html .= html::div(array('class' => 'tagline tagedit', 'style' => 'display:none'), ' '); $html .= html::div(array('class' => 'tagline tagedit', 'style' => 'display:none'), ' ');
@ -247,7 +248,7 @@ class kolab_notes_ui
$form['properties']['fields']['name'] = array( $form['properties']['fields']['name'] = array(
'label' => $this->plugin->gettext('listname'), 'label' => $this->plugin->gettext('listname'),
'value' => $input_name->show($list['editname'], array('disabled' => ($options['norename'] || $options['protected']))), 'value' => $input_name->show($list['editname'], array('disabled' => ($options['norename'] || $options['protected']))),
'id' => 'folder-name', 'id' => 'noteslist-name',
); );
// prevent user from moving folder // prevent user from moving folder
@ -255,10 +256,11 @@ class kolab_notes_ui
$hidden_fields[] = array('name' => 'parent', 'value' => $path_imap); $hidden_fields[] = array('name' => 'parent', 'value' => $path_imap);
} }
else { else {
$select = kolab_storage::folder_selector('note', array('name' => 'parent'), $folder_name); $select = kolab_storage::folder_selector('note', array('name' => 'parent', 'id' => 'parent-folder'), $folder_name);
$form['properties']['fields']['path'] = array( $form['properties']['fields']['path'] = array(
'label' => $this->plugin->gettext('parentfolder'), 'label' => $this->plugin->gettext('parentfolder'),
'value' => $select->show(strlen($folder_name) ? $path_imap : ''), 'value' => $select->show(strlen($folder_name) ? $path_imap : ''),
'id' => 'parent-folder',
); );
} }
@ -289,7 +291,6 @@ class kolab_notes_ui
if (is_array($tab['fields']) && empty($tab['content'])) { if (is_array($tab['fields']) && empty($tab['content'])) {
$table = new html_table(array('cols' => 2)); $table = new html_table(array('cols' => 2));
foreach ($tab['fields'] as $col => $colprop) { foreach ($tab['fields'] as $col => $colprop) {
$colprop['id'] = '_'.$col;
$label = !empty($colprop['label']) ? $colprop['label'] : $this->plugin->gettext($col); $label = !empty($colprop['label']) ? $colprop['label'] : $this->plugin->gettext($col);
$table->add('title', html::label($colprop['id'], Q($label))); $table->add('title', html::label($colprop['id'], Q($label)));

View file

@ -31,6 +31,7 @@ $labels['savein'] = 'Save in';
$labels['savingdata'] = 'Saving data...'; $labels['savingdata'] = 'Saving data...';
$labels['recordnotfound'] = 'Record not found'; $labels['recordnotfound'] = 'Record not found';
$labels['norecordsfound'] = 'No notes found';
$labels['nochanges'] = 'No changes to be saved'; $labels['nochanges'] = 'No changes to be saved';
$labels['entertitle'] = 'Please enter a title for this note!'; $labels['entertitle'] = 'Please enter a title for this note!';
$labels['deletenotesconfirm'] = 'Do you really want to delete the selected notes?'; $labels['deletenotesconfirm'] = 'Do you really want to delete the selected notes?';
@ -46,3 +47,4 @@ $labels['arialabelnotesquicksearchbox'] = 'Notes search input';
$labels['arialabelnotessortmenu'] = 'Notes list sorting options'; $labels['arialabelnotessortmenu'] = 'Notes list sorting options';
$labels['arialabelnotesoptionsmenu'] = 'Notebook actions menu'; $labels['arialabelnotesoptionsmenu'] = 'Notebook actions menu';
$labels['arialabelnotebookform'] = 'Notebook properties'; $labels['arialabelnotebookform'] = 'Notebook properties';
$labels['arialabelmessagereferences'] = 'Linked email messages';

View file

@ -40,6 +40,7 @@ function rcube_kolab_notes_ui(settings)
var search_request; var search_request;
var search_query; var search_query;
var tag_draghelper; var tag_draghelper;
var render_no_focus;
var me = this; var me = this;
/* public members */ /* public members */
@ -112,9 +113,16 @@ function rcube_kolab_notes_ui(settings)
} }
}); });
$(rcmail.gui_objects.notebooks).on('click', 'li a', function(e) {
var id = String($(this).closest('li').attr('id')).replace(/^rcmliknb/, '');
notebookslist.select(id);
e.preventDefault();
return false;
});
// register dbl-click handler to open list edit dialog // register dbl-click handler to open list edit dialog
$(rcmail.gui_objects.notebooks).on('dblclick', 'li:not(.virtual)', function(e){ $(rcmail.gui_objects.notebooks).on('dblclick', 'li:not(.virtual) a', function(e) {
var id = String(this.id).replace(/^rcmliknb/, ''); var id = String($(this).closest('li').attr('id')).replace(/^rcmliknb/, '');
if (me.notebooks[id] && me.notebooks[id].editable) { if (me.notebooks[id] && me.notebooks[id].editable) {
list_edit_dialog(id); list_edit_dialog(id);
} }
@ -137,6 +145,7 @@ function rcube_kolab_notes_ui(settings)
noteslist = new rcube_list_widget(rcmail.gui_objects.noteslist, noteslist = new rcube_list_widget(rcmail.gui_objects.noteslist,
{ multiselect:true, draggable:true, keyboard:true }); { multiselect:true, draggable:true, keyboard:true });
noteslist.addEventListener('select', function(list) { noteslist.addEventListener('select', function(list) {
render_no_focus = rcube_event._last_keyboard_event && $(list.list).has(rcube_event._last_keyboard_event.target);
var selection_changed = list.selection.length != 1 || !me.selected_note || list.selection[0] != me.selected_note.id; var selection_changed = list.selection.length != 1 || !me.selected_note || list.selection[0] != me.selected_note.id;
selection_changed && warn_unsaved_changes(function(){ selection_changed && warn_unsaved_changes(function(){
var note; var note;
@ -183,7 +192,7 @@ function rcube_kolab_notes_ui(settings)
} }
// click-handler on tags list // click-handler on tags list
$(rcmail.gui_objects.notestagslist).on('click', function(e){ $(rcmail.gui_objects.notestagslist).on('click', 'li', function(e){
var item = e.target.nodeName == 'LI' ? $(e.target) : $(e.target).closest('li'), var item = e.target.nodeName == 'LI' ? $(e.target) : $(e.target).closest('li'),
tag = item.data('value'); tag = item.data('value');
@ -198,17 +207,17 @@ function rcube_kolab_notes_ui(settings)
if (tagsfilter.length > 1) if (tagsfilter.length > 1)
index = -1; index = -1;
$('li', this).removeClass('selected'); $('li', rcmail.gui_objects.notestagslist).removeClass('selected').attr('aria-checked', 'false');
tagsfilter = []; tagsfilter = [];
} }
// add tag to filter // add tag to filter
if (index < 0) { if (index < 0) {
item.addClass('selected'); item.addClass('selected').attr('aria-checked', 'true');
tagsfilter.push(tag); tagsfilter.push(tag);
} }
else if (shift) { else if (shift) {
item.removeClass('selected'); item.removeClass('selected').attr('aria-checked', 'false');
var a = tagsfilter.slice(0,index); var a = tagsfilter.slice(0,index);
tagsfilter = a.concat(tagsfilter.slice(index+1)); tagsfilter = a.concat(tagsfilter.slice(index+1));
} }
@ -222,6 +231,11 @@ function rcube_kolab_notes_ui(settings)
e.preventDefault(); e.preventDefault();
return false; return false;
}) })
.on('keypress', 'li', function(e) {
if (e.keyCode == 13) {
$(this).trigger('click', { pointerType:'keyboard' });
}
})
.mousedown(function(e){ .mousedown(function(e){
// disable content selection with the mouse // disable content selection with the mouse
e.preventDefault(); e.preventDefault();
@ -314,6 +328,7 @@ function rcube_kolab_notes_ui(settings)
//spellchecker_rpc_url: '../../../../../?_task=utils&_action=spell_html&_remote=1', //spellchecker_rpc_url: '../../../../../?_task=utils&_action=spell_html&_remote=1',
//spellchecker_language: rcmail.env.spell_lang, //spellchecker_language: rcmail.env.spell_lang,
accessibility_focus: false, accessibility_focus: false,
tabfocus_elements: [':prev','btn-save-note'],
setup: function(ed) { setup: function(ed) {
// make links open on shift-click // make links open on shift-click
ed.on('click', function(e) { ed.on('click', function(e) {
@ -453,7 +468,7 @@ function rcube_kolab_notes_ui(settings)
modal: true, modal: true,
resizable: true, resizable: true,
closeOnEscape: false, closeOnEscape: false,
title: rcmail.gettext((list.id ? 'editlist' : 'createlist'), 'kolab_notes'), title: rcmail.gettext((list.id ? 'editlist' : 'newnotebook'), 'kolab_notes'),
open: function() { open: function() {
$dialog.parent().find('.ui-dialog-buttonset .ui-button').first().addClass('mainaction'); $dialog.parent().find('.ui-dialog-buttonset .ui-button').first().addClass('mainaction');
}, },
@ -707,6 +722,10 @@ function rcube_kolab_notes_ui(settings)
else if (me.selected_note && notesdata[me.selected_note.id]) { else if (me.selected_note && notesdata[me.selected_note.id]) {
noteslist.select(me.selected_note.id); noteslist.select(me.selected_note.id);
} }
else if (!data.data.length) {
console.log(data);
rcmail.display_message(rcmail.gettext('norecordsfound','kolab_notes'), 'info');
}
} }
/** /**
@ -738,7 +757,7 @@ function rcube_kolab_notes_ui(settings)
$.each(typeof data.categories == 'object' && data.categories.length ? data.categories : [''], function(i,val){ $.each(typeof data.categories == 'object' && data.categories.length ? data.categories : [''], function(i,val){
$('<input>') $('<input>')
.attr('name', 'tags[]') .attr('name', 'tags[]')
.attr('tabindex', '2') .attr('tabindex', '0')
.addClass('tag') .addClass('tag')
.val(val) .val(val)
.appendTo(tagline); .appendTo(tagline);
@ -808,8 +827,10 @@ function rcube_kolab_notes_ui(settings)
node = editor.getContentAreaContainer().childNodes[0]; node = editor.getContentAreaContainer().childNodes[0];
if (node) node.tabIndex = content.get(0).tabIndex; if (node) node.tabIndex = content.get(0).tabIndex;
if (me.selected_note.uid) if (me.selected_note.uid) {
editor.getBody().focus(); if (!render_no_focus)
editor.getBody().focus();
}
else else
$('.notetitle', rcmail.gui_objects.noteviewtitle).focus().select(); $('.notetitle', rcmail.gui_objects.noteviewtitle).focus().select();
@ -822,6 +843,8 @@ function rcube_kolab_notes_ui(settings)
$(rcmail.gui_objects.notesdetailview).html(html).show(); $(rcmail.gui_objects.notesdetailview).html(html).show();
} }
render_no_focus = false;
// notify subscribers // notify subscribers
rcmail.triggerEvent('kolab_notes_render', { data:data, readonly:readonly, html:is_html }); rcmail.triggerEvent('kolab_notes_render', { data:data, readonly:readonly, html:is_html });
if (rcmail.is_framed()) if (rcmail.is_framed())
@ -916,7 +939,9 @@ function rcube_kolab_notes_ui(settings)
// append tags to tag cloud // append tags to tag cloud
$.each(tags, function(i, tag){ $.each(tags, function(i, tag){
li = $('<li>').attr('rel', tag).data('value', tag) li = $('<li role="checkbox" aria-checked="false" tabindex="0"></li>')
.attr('rel', tag)
.data('value', tag)
.html(Q(tag) + '<span class="count"></span>') .html(Q(tag) + '<span class="count"></span>')
.appendTo(widget) .appendTo(widget)
.draggable({ .draggable({
@ -961,10 +986,10 @@ function rcube_kolab_notes_ui(settings)
else elem.removeClass('inactive'); else elem.removeClass('inactive');
if (tagsfilter && tagsfilter.length && $.inArray(tag, tagsfilter)) { if (tagsfilter && tagsfilter.length && $.inArray(tag, tagsfilter)) {
elem.addClass('selected'); elem.addClass('selected').attr('aria-checked', 'true');
} }
else { else {
elem.removeClass('selected'); elem.removeClass('selected').attr('aria-checked', 'false');
} }
}); });
} }
@ -1149,7 +1174,9 @@ function rcube_kolab_notes_ui(settings)
dialogClass: 'warning', dialogClass: 'warning',
open: function(event, ui) { open: function(event, ui) {
$(this).parent().find('.ui-dialog-titlebar-close').hide(); $(this).parent().find('.ui-dialog-titlebar-close').hide();
$(this).parent().find('.ui-button').first().addClass('mainaction').focus(); setTimeout(function(){
dialog.parent().find('.ui-button:visible').first().addClass('mainaction').focus();
}, 10);
} }
}; };

View file

@ -88,16 +88,25 @@
bottom: 0px; bottom: 0px;
} }
.notesview #kolabnoteslist li {
border-left: 2px solid transparent;
}
.notesview #kolabnoteslist.focus li.focused {
border-left: 2px solid #739da8;
}
.notesview #kolabnoteslist .title { .notesview #kolabnoteslist .title {
display: block; display: block;
padding: 4px 8px; padding: 4px 6px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
outline: none;
} }
.notesview #kolabnoteslist .date { .notesview #kolabnoteslist .date {
display: block; display: block;
padding: 0px 8px 4px 8px; padding: 0px 6px 4px 6px;
color: #777; color: #777;
font-weight: normal; font-weight: normal;
} }
@ -238,6 +247,7 @@
.notesview #notedetailstitle .tagline { .notesview #notedetailstitle .tagline {
position: relative; position: relative;
cursor: text; cursor: text;
margin: 6px -2px -2px -2px;
} }
.notesview #notedetailstitle .tagline .placeholder { .notesview #notedetailstitle .tagline .placeholder {
@ -250,6 +260,7 @@
.notesview #notedetailstitle .tagedit-list { .notesview #notedetailstitle .tagedit-list {
position: relative; position: relative;
z-index: 2; z-index: 2;
padding: 2px;
} }
.notesview #notedetailstitle #tagedit-input { .notesview #notedetailstitle #tagedit-input {
@ -295,24 +306,25 @@
height: 12px; height: 12px;
} }
.notesview #notebooks li span.listname { .notesview #notebooks li .listname {
display: block; display: block;
position: absolute; position: absolute;
top: 7px; top: 1px;
left: 9px; left: 2px;
right: 6px; right: 6px;
height: 19px;
cursor: default; cursor: default;
padding-bottom: 2px; padding: 4px 26px 2px 6px;
padding-right: 26px;
color: #004458; color: #004458;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
} }
.notesview #notebooks li.virtual span.listname { .notesview #notebooks li.virtual .listname {
color: #aaa; color: #aaa;
top: 3px; top: 0;
padding: 1px 8px;
} }
.notesview #notebooks li.readonly, .notesview #notebooks li.readonly,
@ -343,24 +355,16 @@
background-position: 98% -130px; background-position: 98% -130px;
} }
.notesview #notebooks li.other.readonly span.listname, .notesview #notebooks li.other.readonly .listname,
.notesview #notebooks li.shared.readonly span.listname { .notesview #notebooks li.shared.readonly .listname {
padding-right: 36px; padding-right: 36px;
} }
.notesview #notebooks li.selected > a {
background-color: transparent;
}
.notesview .uidialog .tabbed { .notesview .uidialog .tabbed {
margin-top: -12px; margin-top: -12px;
} }
.notesview .uidialog .propform fieldset.tab { .notesview .uidialog .propform fieldset.ui-tabs-panel {
display: block;
background: #efefef;
margin-top: 0.5em;
padding: 0.5em 1em;
min-height: 290px; min-height: 290px;
} }

View file

@ -31,21 +31,30 @@
<div id="sidebar"> <div id="sidebar">
<div id="tagsbox" class="uibox listbox"> <div id="tagsbox" class="uibox listbox">
<h2 class="boxtitle"><roundcube:label name="kolab_notes.tags" id="taglist" /></h2> <h2 class="boxtitle" id="aria-label-tagsbox"><roundcube:label name="kolab_notes.tags" id="taglist" /></h2>
<div class="scroller"> <div class="scroller">
<roundcube:object name="plugin.tagslist" id="tagslist" class="tagcloud" /> <roundcube:object name="plugin.tagslist" id="tagslist" class="tagcloud" role="region" aria-labelledby="aria-label-tagsbox" aria-controls="kolabnoteslist" />
</div> </div>
</div> </div>
<div id="notebooksbox" class="uibox listbox"> <div id="notebooksbox" class="uibox listbox" role="navigation" aria-labelledby="aria-label-notebooks">
<h2 class="boxtitle"><roundcube:label name="kolab_notes.lists" /></h2> <h2 class="boxtitle" id="aria-label-notebooks"><roundcube:label name="kolab_notes.lists" /></h2>
<div class="scroller withfooter"> <div class="scroller withfooter">
<roundcube:object name="plugin.notebooks" id="notebooks" class="listing" /> <roundcube:object name="plugin.notebooks" id="notebooks" class="listing treelist" />
</div> </div>
<div class="boxfooter"> <div class="boxfooter">
<roundcube:button command="list-create" type="link" title="kolab_notes.newnotebook" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="kolab_notes.addnotebook" /><roundcube:button name="notesoptionslink" id="notesoptionsmenulink" type="link" title="kolab_notes.listactions" class="listbutton groupactions" onclick="return UI.toggle_popup('notesoptionsmenu', event)" innerClass="inner" content="&#9881;" aria-haspopup="true" aria-expanded="false" aria-owns="notesoptionsmenu-menu" /> <roundcube:button command="list-create" type="link" title="kolab_notes.newnotebook" class="listbutton add disabled" classAct="listbutton add" innerClass="inner" label="kolab_notes.addnotebook" /><roundcube:button name="notesoptionslink" id="notesoptionsmenulink" type="link" title="kolab_notes.listactions" class="listbutton groupactions" onclick="return UI.toggle_popup('notesoptionsmenu', event)" innerClass="inner" label="kolab_notes.listactions" aria-haspopup="true" aria-expanded="false" aria-owns="notesoptionsmenu-menu" />
</div> </div>
</div> </div>
<div id="notesoptionsmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-optionsmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotesoptionsmenu" /></h3>
<ul class="toolbarmenu" id="notesoptionsmenu-menu" role="menu" aria-labelledby="aria-label-optionsmenu">
<li role="menuitem"><roundcube:button command="list-edit" label="edit" classAct="active" /></li>
<li role="menuitem"><roundcube:button command="list-remove" label="delete" classAct="active" /></li>
<li role="menuitem"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
</ul>
</div>
</div> </div>
<div id="mainview-right"> <div id="mainview-right">
@ -56,23 +65,24 @@
</div> </div>
<div class="boxfooter"> <div class="boxfooter">
<roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="delete" /> <roundcube:button command="delete" type="link" title="delete" class="listbutton delete disabled" classAct="listbutton delete" innerClass="inner" label="delete" />
<roundcube:object name="plugin.recordsCountDisplay" class="countdisplay" label="fromtoshort" /> <roundcube:object name="plugin.recordsCountDisplay" class="countdisplay" label="fromtoshort" aria-live="polite" aria-relevant="text" />
</div> </div>
<div class="boxpagenav"> <div class="boxpagenav">
<roundcube:button name="notessortmenulink" id="notessortmenulink" type="link" title="kolab_notes.sortby" class="icon sortoptions" onclick="return UI.toggle_popup('notessortmenu', event)" innerClass="inner" content="v" aria-haspopup="true" aria-expanded="false" aria-owns="notessortmenu-menu" /> <roundcube:button name="notessortmenulink" id="notessortmenulink" type="link" title="kolab_notes.sortby" class="icon sortoptions" onclick="return UI.toggle_popup('notessortmenu', event)" innerClass="inner" content="v" aria-haspopup="true" aria-expanded="false" aria-owns="notessortmenu-menu" />
</div> </div>
</div> </div>
<div id="notedetailsbox" class="uibox contentbox" role="complementary" aria-labelledby="aria-label-noteform"> <div id="notedetailsbox" class="uibox contentbox" role="main" aria-labelledby="aria-label-noteform">
<h3 id="aria-label-noteform" class="voice"><roundcube:label name="kolab_notes.arialabelnoteform" /></h3> <h3 id="aria-label-noteform" class="voice"><roundcube:label name="kolab_notes.arialabelnoteform" /></h3>
<roundcube:object name="plugin.notetitle" id="notedetailstitle" class="boxtitle" /> <roundcube:object name="plugin.notetitle" id="notedetailstitle" class="boxtitle" />
<roundcube:object name="plugin.editform" id="noteform" /> <roundcube:object name="plugin.editform" id="noteform" />
<roundcube:object name="plugin.detailview" id="notedetails" class="scroller" /> <roundcube:object name="plugin.detailview" id="notedetails" class="scroller" />
<div id="notereferences"> <div id="notereferences">
<roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" /> <h3 id="aria-label-messagereferences" class="voice"><roundcube:label name="kolab_notes.arialabelmessagereferences" /></h3>
<roundcube:object name="plugin.attachments_list" id="attachment-list" class="attachmentslist" role="region" aria-labelledby="aria-label-messagereferences" />
</div> </div>
<div class="footerleft formbuttons"> <div class="footerleft formbuttons">
<roundcube:button command="save" type="input" class="button mainaction" label="save" /> <roundcube:button command="save" type="input" class="button mainaction" label="save" id="btn-save-note" />
</div> </div>
</div> </div>
</div> </div>
@ -82,15 +92,6 @@
<roundcube:object name="message" id="messagestack" /> <roundcube:object name="message" id="messagestack" />
<div id="notesoptionsmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-optionsmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotesoptionsmenu" /></h3>
<ul class="toolbarmenu" id="notesoptionsmenu-menu" role="menu" aria-labelledby="aria-label-optionsmenu">
<li role="menuitem"><roundcube:button command="list-edit" label="edit" classAct="active" /></li>
<li role="menuitem"><roundcube:button command="list-remove" label="delete" classAct="active" /></li>
<li role="menuitem"><roundcube:button command="folders" task="settings" type="link" label="managefolders" classAct="active" /></li>
</ul>
</div>
<div id="notessortmenu" class="popupmenu" aria-hidden="true"> <div id="notessortmenu" class="popupmenu" aria-hidden="true">
<h3 id="aria-label-sortmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotessortmenu" /></h3> <h3 id="aria-label-sortmenu" class="voice"><roundcube:label name="kolab_notes.arialabelnotessortmenu" /></h3>
<ul class="toolbarmenu iconized" id="notessortmenu-menu" role="menu" aria-labelledby="aria-label-sortmenu"> <ul class="toolbarmenu iconized" id="notessortmenu-menu" role="menu" aria-labelledby="aria-label-sortmenu">