fix: keyboard navigation via tab on forms
This commit is contained in:
parent
c94f26a69d
commit
226eef58c3
11 changed files with 69 additions and 31 deletions
|
|
@ -14,7 +14,7 @@ frappe.ui.form.ControlLink = class ControlLink extends frappe.ui.form.ControlDat
|
|||
$(`<div class="link-field ui-front" style="position: relative;">
|
||||
<input type="text" class="input-with-feedback form-control">
|
||||
<span class="link-btn">
|
||||
<a class="btn-open" style="display: inline-block;" title="${__("Open Link")}">
|
||||
<a class="btn-open" tabIndex='-1' style="display: inline-block;" title="${__("Open Link")}">
|
||||
${frappe.utils.icon("arrow-right", "xs")}
|
||||
</a>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ frappe.ui.form.ControlTable = class ControlTable extends frappe.ui.form.Control
|
|||
this.frm.grids[this.frm.grids.length] = this;
|
||||
}
|
||||
|
||||
this.$wrapper.on("keydown", (e) => {
|
||||
if (e.which == 9) {
|
||||
this.grid.grid_rows[this.grid.grid_rows.length - 1].toggle_editable_row(true);
|
||||
}
|
||||
});
|
||||
this.$wrapper.on("paste", ":text", (e) => {
|
||||
const table_field = this.df.fieldname;
|
||||
const grid = this.grid;
|
||||
|
|
|
|||
|
|
@ -382,6 +382,7 @@ export default class Grid {
|
|||
frm: this.frm,
|
||||
grid: this,
|
||||
configure_columns: true,
|
||||
header_row: true,
|
||||
});
|
||||
|
||||
this.header_search = new GridRow({
|
||||
|
|
@ -939,7 +940,7 @@ export default class Grid {
|
|||
|
||||
setTimeout(() => {
|
||||
this.grid_rows[idx].row
|
||||
.find('input[type="Text"],textarea,select')
|
||||
.find('input[type="checkbox"],input[type="Text"],textarea,select')
|
||||
.filter(":visible:first")
|
||||
.focus();
|
||||
}, 100);
|
||||
|
|
|
|||
|
|
@ -255,6 +255,10 @@ export default class GridRow {
|
|||
? this.doc.idx
|
||||
: __("No.", null, "Title of the 'row number' column");
|
||||
|
||||
if (this.header_row) {
|
||||
this.row_check_html = $(this.row_check_html).attr("tabindex", -1).get(0).outerHTML;
|
||||
}
|
||||
|
||||
this.row_check = $(
|
||||
`<div class="row-check sortable-handle col">
|
||||
${this.row_check_html}
|
||||
|
|
@ -339,7 +343,7 @@ export default class GridRow {
|
|||
if (this.doc && !this.grid.df.in_place_edit) {
|
||||
// remove row
|
||||
if (!this.open_form_button) {
|
||||
this.open_form_button = $('<div class="col"></div>').appendTo(this.row);
|
||||
this.open_form_button = $('<button class="col"></button>').appendTo(this.row);
|
||||
|
||||
if (!this.configure_columns) {
|
||||
const edit_msg = __("Edit", "", "Edit grid row");
|
||||
|
|
@ -353,6 +357,14 @@ export default class GridRow {
|
|||
me.toggle_view();
|
||||
return false;
|
||||
});
|
||||
$(this.open_form_button)
|
||||
.parent()
|
||||
.on("keydown", function (ev) {
|
||||
if (ev.key == "Enter") {
|
||||
me.toggle_view();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
this.open_form_button.tooltip({ delay: { show: 600, hide: 100 } });
|
||||
}
|
||||
|
|
@ -361,6 +373,10 @@ export default class GridRow {
|
|||
// narrow
|
||||
this.open_form_button.css({ "margin-right": "-2px" });
|
||||
}
|
||||
// focus open form button after escape
|
||||
$(document).on("escape", function () {
|
||||
me.open_form_button.parent().focus();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1191,7 +1207,6 @@ export default class GridRow {
|
|||
this.on_grid_fields_dict[df.fieldname] = field;
|
||||
this.on_grid_fields.push(field);
|
||||
}
|
||||
|
||||
set_arrow_keys(field) {
|
||||
var me = this;
|
||||
let ignore_fieldtypes = ["Text", "Small Text", "Code", "Text Editor", "HTML Editor"];
|
||||
|
|
@ -1242,28 +1257,7 @@ export default class GridRow {
|
|||
}
|
||||
|
||||
// TAB
|
||||
if (e.which === TAB && !e.shiftKey) {
|
||||
var last_column = me.wrapper.find(":input:enabled:last").get(0);
|
||||
var is_last_column = $(this).attr("data-last-input") || last_column === this;
|
||||
|
||||
if (is_last_column) {
|
||||
// last row
|
||||
if (me.doc.idx === values.length) {
|
||||
setTimeout(function () {
|
||||
me.grid.add_new_row(null, null, true);
|
||||
me.grid.grid_rows[
|
||||
me.grid.grid_rows.length - 1
|
||||
].toggle_editable_row();
|
||||
me.grid.set_focus_on_row();
|
||||
}, 100);
|
||||
} else {
|
||||
// last column before last row
|
||||
me.grid.grid_rows[me.doc.idx].toggle_editable_row();
|
||||
me.grid.set_focus_on_row(me.doc.idx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (e.which === UP_ARROW) {
|
||||
if (e.which === UP_ARROW) {
|
||||
if (me.doc.idx > 1) {
|
||||
var prev = me.grid.grid_rows[me.doc.idx - 2];
|
||||
if (move_up_down(prev)) {
|
||||
|
|
@ -1360,7 +1354,6 @@ export default class GridRow {
|
|||
this.hide_form();
|
||||
}
|
||||
callback && callback();
|
||||
|
||||
return this;
|
||||
}
|
||||
show_form() {
|
||||
|
|
@ -1373,6 +1366,7 @@ export default class GridRow {
|
|||
row: this,
|
||||
});
|
||||
}
|
||||
this.grid_form.wrapper.css("display", "block");
|
||||
this.grid_form.render();
|
||||
this.row.toggle(false);
|
||||
// this.form_panel.toggle(true);
|
||||
|
|
@ -1417,7 +1411,11 @@ export default class GridRow {
|
|||
}
|
||||
this.refresh();
|
||||
if (cur_frm) cur_frm.cur_grid = null;
|
||||
if (this.grid_form) {
|
||||
this.grid_form.wrapper.css("display", "none");
|
||||
}
|
||||
this.wrapper.removeClass("grid-row-open");
|
||||
this.open_form_button.parent().focus();
|
||||
}
|
||||
has_prev() {
|
||||
return this.doc.idx > 1;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ frappe.ui.form.Layout = class Layout {
|
|||
this.setup_tabbed_layout();
|
||||
}
|
||||
|
||||
this.setup_tab_events();
|
||||
this.frm && this.setup_tooltip_events();
|
||||
this.render();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,8 +78,14 @@ export default class Section {
|
|||
this.collapse_link = this.head.on("click", () => {
|
||||
this.collapse();
|
||||
});
|
||||
const me = this;
|
||||
this.collapse_link.enterKey(function () {
|
||||
me.collapse();
|
||||
});
|
||||
this.set_icon();
|
||||
this.indicator.show();
|
||||
this.head.attr("tabindex", 0);
|
||||
this.indicator.attr("tabindex", 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,14 +16,14 @@ export default class Tab {
|
|||
const id = `${frappe.scrub(this.doctype, "-")}-${this.df.fieldname}`;
|
||||
this.tab_link = $(`
|
||||
<li class="nav-item">
|
||||
<a class="nav-link ${this.df.active ? "active" : ""}" id="${id}-tab"
|
||||
<button class="nav-link ${this.df.active ? "active" : ""}" id="${id}-tab"
|
||||
data-toggle="tab"
|
||||
data-fieldname="${this.df.fieldname}"
|
||||
href="#${id}"
|
||||
role="tab"
|
||||
aria-controls="${id}">
|
||||
${__(this.label, null, this.doctype)}
|
||||
</a>
|
||||
</button>
|
||||
</li>
|
||||
`).appendTo(this.tab_link_container);
|
||||
|
||||
|
|
|
|||
|
|
@ -331,6 +331,7 @@ frappe.ui.keyCode = {
|
|||
function handle_escape_key() {
|
||||
close_grid_and_dialog();
|
||||
document.activeElement?.blur();
|
||||
$(document).trigger("escape");
|
||||
}
|
||||
|
||||
function close_grid_and_dialog() {
|
||||
|
|
@ -365,3 +366,14 @@ frappe.ui.keys.add_shortcut({
|
|||
},
|
||||
description: __("Open console"),
|
||||
});
|
||||
|
||||
$.fn.enterKey = function (fnc) {
|
||||
return this.each(function () {
|
||||
$(this).keypress(function (ev) {
|
||||
var keycode = ev.keyCode ? ev.keyCode : ev.which;
|
||||
if (keycode == "13") {
|
||||
fnc.call(this, ev);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
|
|
@ -82,6 +82,9 @@
|
|||
background-color: var(--btn-default-hover-bg);
|
||||
color: var(--text-color);
|
||||
}
|
||||
&:focus {
|
||||
box-shadow: var(--focus-default) !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn.btn-default {
|
||||
|
|
|
|||
|
|
@ -136,6 +136,9 @@
|
|||
.row-index {
|
||||
left: 31px;
|
||||
}
|
||||
button.col:focus {
|
||||
outline: 1px solid #c9c9c9;
|
||||
}
|
||||
}
|
||||
|
||||
.grid-empty,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@
|
|||
margin-left: 10px;
|
||||
position: relative;
|
||||
padding: 0px;
|
||||
&:focus {
|
||||
outline: 1px solid #c9c9c9;
|
||||
}
|
||||
}
|
||||
&:focus {
|
||||
outline: 1px solid #c9c9c9;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -500,13 +506,18 @@
|
|||
color: var(--text-muted);
|
||||
padding: 10px 0;
|
||||
margin: 0 var(--margin-md);
|
||||
|
||||
background-color: var(--card-bg);
|
||||
border: 0;
|
||||
&.active {
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid var(--text-color);
|
||||
color: var(--text-color);
|
||||
padding-bottom: 9px;
|
||||
}
|
||||
&:focus {
|
||||
outline: none;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue