summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/web/static/src/js/views/abstract_controller.js11
-rw-r--r--addons/web/static/src/js/views/control_panel/control_panel_controller.js8
-rw-r--r--addons/web/static/src/js/views/control_panel/search/search_bar.js8
-rw-r--r--addons/web/static/src/js/views/kanban/kanban_renderer.js9
-rw-r--r--addons/web/static/src/js/views/list/list_editable_renderer.js4
-rw-r--r--addons/web/static/src/js/views/list/list_renderer.js3
-rw-r--r--addons/web/static/tests/views/list_tests.js11
7 files changed, 44 insertions, 10 deletions
diff --git a/addons/web/static/src/js/views/abstract_controller.js b/addons/web/static/src/js/views/abstract_controller.js
index 07a0109e9a7..cb83301c14d 100644
--- a/addons/web/static/src/js/views/abstract_controller.js
+++ b/addons/web/static/src/js/views/abstract_controller.js
@@ -559,15 +559,19 @@ var AbstractController = mvc.Controller.extend(ActionMixin, {
ev.data.callback(state || {});
},
/**
- * Called mainly from the control panel when the focus should be given to
- * the controller
+ * Called either from the control panel to focus the controller
+ * or from the view to focus the search bar
*
* @private
* @param {OdooEvent} ev
*/
_onNavigationMove: function (ev) {
switch (ev.data.direction) {
- case 'down' :
+ case 'up':
+ ev.stopPropagation();
+ this._controlPanel.focusSearchBar();
+ break;
+ case 'down':
ev.stopPropagation();
this.giveFocus();
break;
@@ -629,7 +633,6 @@ var AbstractController = mvc.Controller.extend(ActionMixin, {
_onSwitchView: function (ev) {
ev.data.controllerID = this.controllerID;
},
-
});
return AbstractController;
diff --git a/addons/web/static/src/js/views/control_panel/control_panel_controller.js b/addons/web/static/src/js/views/control_panel/control_panel_controller.js
index dc8fce9f5d1..3c23e681631 100644
--- a/addons/web/static/src/js/views/control_panel/control_panel_controller.js
+++ b/addons/web/static/src/js/views/control_panel/control_panel_controller.js
@@ -55,6 +55,14 @@ var ControlPanelController = mvc.Controller.extend({
return this.model.exportState();
},
/**
+ * Called by the abstract controller to give focus to the searchbar
+ */
+ focusSearchBar: function () {
+ if (this.renderer.searchBar) {
+ this.renderer.searchBar.focus();
+ }
+ },
+ /**
* Compute the search related values that will be used to fetch data.
*
* @returns {Object} object with keys 'context', 'domain', 'groupBy'
diff --git a/addons/web/static/src/js/views/control_panel/search/search_bar.js b/addons/web/static/src/js/views/control_panel/search/search_bar.js
index 6248489922c..d4efab663d4 100644
--- a/addons/web/static/src/js/views/control_panel/search/search_bar.js
+++ b/addons/web/static/src/js/views/control_panel/search/search_bar.js
@@ -221,6 +221,14 @@ var SearchBar = Widget.extend({
this._focusFollowing();
e.preventDefault();
break;
+ case $.ui.keyCode.DOWN:
+ // if the searchbar dropdown is closed, try to focus the renderer
+ const $dropdown = this.$('.o_searchview_autocomplete:visible');
+ if (!$dropdown.length) {
+ this.trigger_up('navigation_move', { direction: 'down' });
+ e.preventDefault();
+ }
+ break;
case $.ui.keyCode.BACKSPACE:
if (this.$input.val() === '') {
this.trigger_up('facet_removed');
diff --git a/addons/web/static/src/js/views/kanban/kanban_renderer.js b/addons/web/static/src/js/views/kanban/kanban_renderer.js
index 30feb56cb2c..8f6d7b628f6 100644
--- a/addons/web/static/src/js/views/kanban/kanban_renderer.js
+++ b/addons/web/static/src/js/views/kanban/kanban_renderer.js
@@ -262,13 +262,17 @@ var KanbanRenderer = BasicRenderer.extend({
}
},
/**
+ * Tries to give focus to the previous card, and returns true if successful
+ *
* @private
* @param {DOMElement} currentColumn
+ * @returns {boolean}
*/
_focusOnPreviousCard: function (currentCardElement) {
var previousCard = currentCardElement.previousElementSibling;
if (previousCard && previousCard.classList.contains("o_kanban_record")) { //previous element might be column title
previousCard.focus();
+ return true;
}
},
/**
@@ -611,7 +615,10 @@ var KanbanRenderer = BasicRenderer.extend({
e.preventDefault();
break;
case $.ui.keyCode.UP:
- this._focusOnPreviousCard(e.currentTarget);
+ const previousFocused = this._focusOnPreviousCard(e.currentTarget);
+ if (!previousFocused) {
+ this.trigger_up('navigation_move', { direction: 'up' });
+ }
e.stopPropagation();
e.preventDefault();
break;
diff --git a/addons/web/static/src/js/views/list/list_editable_renderer.js b/addons/web/static/src/js/views/list/list_editable_renderer.js
index 65bae3eea41..71f20878e88 100644
--- a/addons/web/static/src/js/views/list/list_editable_renderer.js
+++ b/addons/web/static/src/js/views/list/list_editable_renderer.js
@@ -1155,6 +1155,10 @@ ListRenderer.include({
*/
_onNavigationMove: function (ev) {
var self = this;
+ // Don't stop the propagation when navigating up while not editing any row
+ if (this.currentRow === null && ev.data.direction === 'up') {
+ return;
+ }
ev.stopPropagation(); // stop the event, the action is done by this renderer
switch (ev.data.direction) {
case 'previous':
diff --git a/addons/web/static/src/js/views/list/list_renderer.js b/addons/web/static/src/js/views/list/list_renderer.js
index 2ddf21b1ef8..5e54b626573 100644
--- a/addons/web/static/src/js/views/list/list_renderer.js
+++ b/addons/web/static/src/js/views/list/list_renderer.js
@@ -1108,6 +1108,9 @@ var ListRenderer = BasicRenderer.extend({
$cell.closest('tbody').addClass('o_keyboard_navigation');
colIndex = this.currentColIndex || $cell.index();
$futureCell = this._findConnectedCell($cell, 'prev', colIndex);
+ if (!$futureCell) {
+ this.trigger_up('navigation_move', { direction: 'up' });
+ }
break;
case $.ui.keyCode.DOWN:
ev.preventDefault();
diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js
index 4c1ff4c10ae..48c0502b689 100644
--- a/addons/web/static/tests/views/list_tests.js
+++ b/addons/web/static/tests/views/list_tests.js
@@ -5883,14 +5883,15 @@ QUnit.module('Views', {
},
});
- assert.ok(document.activeElement.classList.contains('o_searchview_input'), 'default focus should be in search view');
- // switch focus to the create button in tests while it works on live
- $('.o_list_button_add').focus();
- assert.ok(document.activeElement.classList.contains('o_list_button_add'),
- 'focus should now be in create button');
+ assert.ok(document.activeElement.classList.contains('o_searchview_input'),
+ 'default focus should be in search view');
await testUtils.fields.triggerKeydown($(document.activeElement), 'down');
assert.strictEqual(document.activeElement.tagName, 'INPUT',
'focus should now be on the record selector');
+ await testUtils.fields.triggerKeydown($(document.activeElement), 'up');
+ assert.ok(document.activeElement.classList.contains('o_searchview_input'),
+ 'focus should have come back to the search view');
+ await testUtils.fields.triggerKeydown($(document.activeElement), 'down');
await testUtils.fields.triggerKeydown($(document.activeElement), 'down');
assert.strictEqual(document.activeElement.tagName, 'INPUT',
'focus should now be in first row input');