Finalize accessibility improvements for the notes module (#3088)
This commit is contained in:
parent
982b673d37
commit
e26c4836bc
5 changed files with 94 additions and 59 deletions
|
@ -135,8 +135,9 @@ class kolab_notes_ui
|
|||
if ($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)),
|
||||
html::span(array('class' => 'listname', 'title' => $title), $prop['listname']) .
|
||||
html::a($attr + array('class' => 'listname', 'title' => $title), $prop['listname']) .
|
||||
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->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')));
|
||||
}
|
||||
|
||||
|
@ -185,7 +186,7 @@ class kolab_notes_ui
|
|||
$attrib += array('id' => 'rcmkolabnotestitle');
|
||||
$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 .= html::div(array('class' => 'tagline tagedit', 'style' => 'display:none'), ' ');
|
||||
|
@ -247,7 +248,7 @@ class kolab_notes_ui
|
|||
$form['properties']['fields']['name'] = array(
|
||||
'label' => $this->plugin->gettext('listname'),
|
||||
'value' => $input_name->show($list['editname'], array('disabled' => ($options['norename'] || $options['protected']))),
|
||||
'id' => 'folder-name',
|
||||
'id' => 'noteslist-name',
|
||||
);
|
||||
|
||||
// prevent user from moving folder
|
||||
|
@ -255,10 +256,11 @@ class kolab_notes_ui
|
|||
$hidden_fields[] = array('name' => 'parent', 'value' => $path_imap);
|
||||
}
|
||||
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(
|
||||
'label' => $this->plugin->gettext('parentfolder'),
|
||||
'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'])) {
|
||||
$table = new html_table(array('cols' => 2));
|
||||
foreach ($tab['fields'] as $col => $colprop) {
|
||||
$colprop['id'] = '_'.$col;
|
||||
$label = !empty($colprop['label']) ? $colprop['label'] : $this->plugin->gettext($col);
|
||||
|
||||
$table->add('title', html::label($colprop['id'], Q($label)));
|
||||
|
|
|
@ -31,6 +31,7 @@ $labels['savein'] = 'Save in';
|
|||
|
||||
$labels['savingdata'] = 'Saving data...';
|
||||
$labels['recordnotfound'] = 'Record not found';
|
||||
$labels['norecordsfound'] = 'No notes found';
|
||||
$labels['nochanges'] = 'No changes to be saved';
|
||||
$labels['entertitle'] = 'Please enter a title for this note!';
|
||||
$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['arialabelnotesoptionsmenu'] = 'Notebook actions menu';
|
||||
$labels['arialabelnotebookform'] = 'Notebook properties';
|
||||
$labels['arialabelmessagereferences'] = 'Linked email messages';
|
||||
|
|
|
@ -40,6 +40,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
var search_request;
|
||||
var search_query;
|
||||
var tag_draghelper;
|
||||
var render_no_focus;
|
||||
var me = this;
|
||||
|
||||
/* 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
|
||||
$(rcmail.gui_objects.notebooks).on('dblclick', 'li:not(.virtual)', function(e){
|
||||
var id = String(this.id).replace(/^rcmliknb/, '');
|
||||
$(rcmail.gui_objects.notebooks).on('dblclick', 'li:not(.virtual) a', function(e) {
|
||||
var id = String($(this).closest('li').attr('id')).replace(/^rcmliknb/, '');
|
||||
if (me.notebooks[id] && me.notebooks[id].editable) {
|
||||
list_edit_dialog(id);
|
||||
}
|
||||
|
@ -137,6 +145,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
noteslist = new rcube_list_widget(rcmail.gui_objects.noteslist,
|
||||
{ multiselect:true, draggable:true, keyboard:true });
|
||||
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;
|
||||
selection_changed && warn_unsaved_changes(function(){
|
||||
var note;
|
||||
|
@ -183,7 +192,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
}
|
||||
|
||||
// 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'),
|
||||
tag = item.data('value');
|
||||
|
||||
|
@ -198,17 +207,17 @@ function rcube_kolab_notes_ui(settings)
|
|||
if (tagsfilter.length > 1)
|
||||
index = -1;
|
||||
|
||||
$('li', this).removeClass('selected');
|
||||
$('li', rcmail.gui_objects.notestagslist).removeClass('selected').attr('aria-checked', 'false');
|
||||
tagsfilter = [];
|
||||
}
|
||||
|
||||
// add tag to filter
|
||||
if (index < 0) {
|
||||
item.addClass('selected');
|
||||
item.addClass('selected').attr('aria-checked', 'true');
|
||||
tagsfilter.push(tag);
|
||||
}
|
||||
else if (shift) {
|
||||
item.removeClass('selected');
|
||||
item.removeClass('selected').attr('aria-checked', 'false');
|
||||
var a = tagsfilter.slice(0,index);
|
||||
tagsfilter = a.concat(tagsfilter.slice(index+1));
|
||||
}
|
||||
|
@ -222,6 +231,11 @@ function rcube_kolab_notes_ui(settings)
|
|||
e.preventDefault();
|
||||
return false;
|
||||
})
|
||||
.on('keypress', 'li', function(e) {
|
||||
if (e.keyCode == 13) {
|
||||
$(this).trigger('click', { pointerType:'keyboard' });
|
||||
}
|
||||
})
|
||||
.mousedown(function(e){
|
||||
// disable content selection with the mouse
|
||||
e.preventDefault();
|
||||
|
@ -314,6 +328,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
//spellchecker_rpc_url: '../../../../../?_task=utils&_action=spell_html&_remote=1',
|
||||
//spellchecker_language: rcmail.env.spell_lang,
|
||||
accessibility_focus: false,
|
||||
tabfocus_elements: [':prev','btn-save-note'],
|
||||
setup: function(ed) {
|
||||
// make links open on shift-click
|
||||
ed.on('click', function(e) {
|
||||
|
@ -453,7 +468,7 @@ function rcube_kolab_notes_ui(settings)
|
|||
modal: true,
|
||||
resizable: true,
|
||||
closeOnEscape: false,
|
||||
title: rcmail.gettext((list.id ? 'editlist' : 'createlist'), 'kolab_notes'),
|
||||
title: rcmail.gettext((list.id ? 'editlist' : 'newnotebook'), 'kolab_notes'),
|
||||
open: function() {
|
||||
$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]) {
|
||||
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){
|
||||
$('<input>')
|
||||
.attr('name', 'tags[]')
|
||||
.attr('tabindex', '2')
|
||||
.attr('tabindex', '0')
|
||||
.addClass('tag')
|
||||
.val(val)
|
||||
.appendTo(tagline);
|
||||
|
@ -808,8 +827,10 @@ function rcube_kolab_notes_ui(settings)
|
|||
node = editor.getContentAreaContainer().childNodes[0];
|
||||
if (node) node.tabIndex = content.get(0).tabIndex;
|
||||
|
||||
if (me.selected_note.uid)
|
||||
editor.getBody().focus();
|
||||
if (me.selected_note.uid) {
|
||||
if (!render_no_focus)
|
||||
editor.getBody().focus();
|
||||
}
|
||||
else
|
||||
$('.notetitle', rcmail.gui_objects.noteviewtitle).focus().select();
|
||||
|
||||
|
@ -822,6 +843,8 @@ function rcube_kolab_notes_ui(settings)
|
|||
$(rcmail.gui_objects.notesdetailview).html(html).show();
|
||||
}
|
||||
|
||||
render_no_focus = false;
|
||||
|
||||
// notify subscribers
|
||||
rcmail.triggerEvent('kolab_notes_render', { data:data, readonly:readonly, html:is_html });
|
||||
if (rcmail.is_framed())
|
||||
|
@ -916,7 +939,9 @@ function rcube_kolab_notes_ui(settings)
|
|||
|
||||
// append tags to tag cloud
|
||||
$.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>')
|
||||
.appendTo(widget)
|
||||
.draggable({
|
||||
|
@ -961,10 +986,10 @@ function rcube_kolab_notes_ui(settings)
|
|||
else elem.removeClass('inactive');
|
||||
|
||||
if (tagsfilter && tagsfilter.length && $.inArray(tag, tagsfilter)) {
|
||||
elem.addClass('selected');
|
||||
elem.addClass('selected').attr('aria-checked', 'true');
|
||||
}
|
||||
else {
|
||||
elem.removeClass('selected');
|
||||
elem.removeClass('selected').attr('aria-checked', 'false');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1149,7 +1174,9 @@ function rcube_kolab_notes_ui(settings)
|
|||
dialogClass: 'warning',
|
||||
open: function(event, ui) {
|
||||
$(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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -88,16 +88,25 @@
|
|||
bottom: 0px;
|
||||
}
|
||||
|
||||
.notesview #kolabnoteslist li {
|
||||
border-left: 2px solid transparent;
|
||||
}
|
||||
|
||||
.notesview #kolabnoteslist.focus li.focused {
|
||||
border-left: 2px solid #739da8;
|
||||
}
|
||||
|
||||
.notesview #kolabnoteslist .title {
|
||||
display: block;
|
||||
padding: 4px 8px;
|
||||
padding: 4px 6px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.notesview #kolabnoteslist .date {
|
||||
display: block;
|
||||
padding: 0px 8px 4px 8px;
|
||||
padding: 0px 6px 4px 6px;
|
||||
color: #777;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
@ -238,6 +247,7 @@
|
|||
.notesview #notedetailstitle .tagline {
|
||||
position: relative;
|
||||
cursor: text;
|
||||
margin: 6px -2px -2px -2px;
|
||||
}
|
||||
|
||||
.notesview #notedetailstitle .tagline .placeholder {
|
||||
|
@ -250,6 +260,7 @@
|
|||
.notesview #notedetailstitle .tagedit-list {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.notesview #notedetailstitle #tagedit-input {
|
||||
|
@ -295,24 +306,25 @@
|
|||
height: 12px;
|
||||
}
|
||||
|
||||
.notesview #notebooks li span.listname {
|
||||
.notesview #notebooks li .listname {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: 9px;
|
||||
top: 1px;
|
||||
left: 2px;
|
||||
right: 6px;
|
||||
height: 19px;
|
||||
cursor: default;
|
||||
padding-bottom: 2px;
|
||||
padding-right: 26px;
|
||||
padding: 4px 26px 2px 6px;
|
||||
color: #004458;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.notesview #notebooks li.virtual span.listname {
|
||||
.notesview #notebooks li.virtual .listname {
|
||||
color: #aaa;
|
||||
top: 3px;
|
||||
top: 0;
|
||||
padding: 1px 8px;
|
||||
}
|
||||
|
||||
.notesview #notebooks li.readonly,
|
||||
|
@ -343,24 +355,16 @@
|
|||
background-position: 98% -130px;
|
||||
}
|
||||
|
||||
.notesview #notebooks li.other.readonly span.listname,
|
||||
.notesview #notebooks li.shared.readonly span.listname {
|
||||
.notesview #notebooks li.other.readonly .listname,
|
||||
.notesview #notebooks li.shared.readonly .listname {
|
||||
padding-right: 36px;
|
||||
}
|
||||
|
||||
.notesview #notebooks li.selected > a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.notesview .uidialog .tabbed {
|
||||
margin-top: -12px;
|
||||
}
|
||||
|
||||
.notesview .uidialog .propform fieldset.tab {
|
||||
display: block;
|
||||
background: #efefef;
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em 1em;
|
||||
.notesview .uidialog .propform fieldset.ui-tabs-panel {
|
||||
min-height: 290px;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,21 +31,30 @@
|
|||
|
||||
<div id="sidebar">
|
||||
<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">
|
||||
<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 id="notebooksbox" class="uibox listbox">
|
||||
<h2 class="boxtitle"><roundcube:label name="kolab_notes.lists" /></h2>
|
||||
<div id="notebooksbox" class="uibox listbox" role="navigation" aria-labelledby="aria-label-notebooks">
|
||||
<h2 class="boxtitle" id="aria-label-notebooks"><roundcube:label name="kolab_notes.lists" /></h2>
|
||||
<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 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="⚙" 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 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 id="mainview-right">
|
||||
|
@ -56,23 +65,24 @@
|
|||
</div>
|
||||
<div class="boxfooter">
|
||||
<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 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" />
|
||||
</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>
|
||||
<roundcube:object name="plugin.notetitle" id="notedetailstitle" class="boxtitle" />
|
||||
<roundcube:object name="plugin.editform" id="noteform" />
|
||||
<roundcube:object name="plugin.detailview" id="notedetails" class="scroller" />
|
||||
<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 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>
|
||||
|
@ -82,15 +92,6 @@
|
|||
|
||||
<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">
|
||||
<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">
|
||||
|
|
Loading…
Add table
Reference in a new issue