From 5a58cb281708542d3bf1f8d3d62f18cb54cc8fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Fri, 28 Apr 2017 15:34:22 +0200 Subject: [PATCH] [FIX] web: better navigation in editable list When the user press the TAB key on the last cell of an editable list, it is supposed to create a new line. --- .../js/views/list/list_editable_renderer.js | 56 +++++++++++-------- addons/web/static/tests/views/list_tests.js | 33 +++++++++++ 2 files changed, 66 insertions(+), 23 deletions(-) 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 54c85e9c888..151d41e2e97 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 @@ -246,6 +246,20 @@ ListRenderer.include({ } return n; }, + /** + * Move the cursor one the beginning of the next line, if possible. + * If there is no next line, then we create a new record. + * + * @private + */ + _moveToNextLine: function () { + if (this.currentRow < this.state.data.length - 1) { + this._selectCell(this.currentRow + 1, 0); + } else { + this._unselectRow(); + this.trigger_up('add_record'); + } + }, /** * @override * @returns {Deferred} @@ -506,18 +520,6 @@ ListRenderer.include({ this._selectCell(rowIndex, colIndex); } }, - /** - * If the list view editable, just let the event bubble. We don't want to - * open the record in this case anyway. - * - * @override - * @private - */ - _onRowClicked: function () { - if (this.mode === 'readonly' || !this.editable) { - this._super.apply(this, arguments); - } - }, /** * We need to manually unselect row, because noone else would do it */ @@ -561,21 +563,17 @@ ListRenderer.include({ ev.stopPropagation(); if (this.currentCol + 1 < this.columns.length) { this._selectCell(this.currentRow, this.currentCol + 1); - } else if (this.currentRow < this.state.data.length - 1) { - this._selectCell(this.currentRow + 1, 0); + } else { + this._moveToNextLine(); } }, /** - * Move the cursor one the beginning of the next line, if possible. This is - * called when the user press the ENTER key. + * @private + * @param {OdooEvent} event */ - _onMoveNextLine: function () { - if (this.currentRow < this.state.data.length - 1) { - this._selectCell(this.currentRow + 1, 0); - } else { - this._unselectRow(); - this.trigger_up('add_record'); - } + _onMoveNextLine: function (event) { + event.stopPropagation(); + this._moveToNextLine(); }, /** * Move the cursor on the previous available cell, so either the previous @@ -610,6 +608,18 @@ ListRenderer.include({ this._selectCell(this.currentRow - 1, this.currentCol); } }, + /** + * If the list view editable, just let the event bubble. We don't want to + * open the record in this case anyway. + * + * @override + * @private + */ + _onRowClicked: function () { + if (this.mode === 'readonly' || !this.editable) { + this._super.apply(this, arguments); + } + }, /** * Triggers a delete event. I don't know why we stop the propagation of the * event. diff --git a/addons/web/static/tests/views/list_tests.js b/addons/web/static/tests/views/list_tests.js index d3c46c3f9f7..92656d024c1 100644 --- a/addons/web/static/tests/views/list_tests.js +++ b/addons/web/static/tests/views/list_tests.js @@ -1584,6 +1584,39 @@ QUnit.module('Views', { list.destroy(); }); + QUnit.test('pressing tab on last cell of editable list view', function (assert) { + assert.expect(7); + + var list = createView({ + View: ListView, + model: 'foo', + data: this.data, + arch: '', + mockRPC: function (route) { + assert.step(route); + return this._super.apply(this, arguments); + }, + }); + + list.$('td:contains(blip)').last().click(); + assert.strictEqual(document.activeElement.name, "foo", + "focus should be on an input with name = foo"); + + list.$('tr.o_selected_row input[name="foo"]').trigger({type: 'keydown', which: 9}); // tab + assert.strictEqual(document.activeElement.name, "int_field", + "focus should be on an input with name = int_field"); + + list.$('tr.o_selected_row input[name="int_field"]').trigger({type: 'keydown', which: 9}); // tab + + assert.ok(list.$('tr.o_data_row:eq(4)').hasClass('o_selected_row'), + "5th row should be selected"); + assert.strictEqual(document.activeElement.name, "foo", + "focus should be on an input with name = foo"); + + assert.verifySteps(['/web/dataset/search_read', '/web/dataset/call_kw/foo/default_get']); + list.destroy(); + }); + }); });