diff options
| author | Julien Mougenot <jum@odoo.com> | 2019-07-12 09:25:16 +0000 |
|---|---|---|
| committer | Julien Mougenot <jum@odoo.com> | 2019-08-16 09:03:49 +0000 |
| commit | bec84c10a1f683f9cc37e76d7fb354ed066508f4 (patch) | |
| tree | 67b7805df8ea10e14fb52dd8c69c2e61bbbd7063 /addons/web/static/src/js/views | |
| parent | 0aea29da8db6821a021a705c68985d7d38d476b1 (diff) | |
[IMP] web: keyboard navigation between searchbar and renderer
This change allows direct keyboard navigation between the current action
searchbar and renderer.
Focus can now be toggled using DOWN arrow when focusing the searchbar
or the UP arrow when focusing the top cell/record of a kanban or a list.
Diffstat (limited to 'addons/web/static/src/js/views')
6 files changed, 38 insertions, 5 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(); |
