From e1edd62320fef4991ba9554ee197021b45987a60 Mon Sep 17 00:00:00 2001 From: David Monjoie Date: Fri, 5 May 2017 16:34:54 +0200 Subject: [PATCH] [FIX] web: toggle checkboxes when clicked in editable list view Previously, the checkbox was not checked when it was clicked in editable list view, it only opened the row but did not check the checkbox. --- .../static/src/js/fields/abstract_field.js | 10 +++++--- .../web/static/src/js/fields/basic_fields.js | 17 +++++++++++++ .../src/js/views/basic/basic_renderer.js | 2 +- .../static/src/js/views/form/form_renderer.js | 2 +- .../js/views/list/list_editable_renderer.js | 25 ++++++++++++------- .../static/tests/fields/basic_fields_tests.js | 6 ++--- 6 files changed, 44 insertions(+), 18 deletions(-) diff --git a/addons/web/static/src/js/fields/abstract_field.js b/addons/web/static/src/js/fields/abstract_field.js index 7278e45dedb..725a237750d 100644 --- a/addons/web/static/src/js/fields/abstract_field.js +++ b/addons/web/static/src/js/fields/abstract_field.js @@ -168,18 +168,20 @@ var AbstractField = Widget.extend({ * part can be disabled. In that case, note that the focused input/textarea * will have the cursor at the very end. * - * @param {boolean} [noselect=false] if false and the input is of type text - * or textarea, the content will also be selected + * @param {Object} [options] + * @param {boolean} [noselect=false] if false and the input + * is of type text or textarea, the content will also be selected + * @param {Event} [options.event] the event which fired this activation * @returns {boolean} true if the widget was activated, false if the * focusable element was not found or invisible */ - activate: function (noselect) { + activate: function (options) { var $focusable = this.getFocusableElement(); if ($focusable.length && $focusable.is(':visible')) { $focusable.focus(); if ($focusable.is('input[type="text"], textarea')) { $focusable[0].selectionStart = $focusable[0].selectionEnd = $focusable[0].value.length; - if (!noselect) { + if (options && !options.noselect) { $focusable.select(); } } diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 3e9ea89be31..6fc1736870f 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -581,6 +581,23 @@ var FieldBoolean = AbstractField.extend({ // Public //-------------------------------------------------------------------------- + /** + * Toggle the checkbox if it is activated due to a click on itself. + * + * @override + */ + activate: function (options) { + var activated = this._super.apply(this, arguments); + // The formatValue of boolean fields renders HTML elements similar to + // the one rendered by the widget itself. Even though the event might + // have been fired on the non-widget version of this field, we can still + // test the presence of its o_checkbox class. + if (activated && options && options.event && $(options.event.target).parents('.o_checkbox').length) { + this._setValue(!this.value); // Toggle the checkbox + } + return activated; + }, + /** * @override * @returns {jQuery} the focusable checkbox input diff --git a/addons/web/static/src/js/views/basic/basic_renderer.js b/addons/web/static/src/js/views/basic/basic_renderer.js index 5babc71ab6b..907ea7ddc07 100644 --- a/addons/web/static/src/js/views/basic/basic_renderer.js +++ b/addons/web/static/src/js/views/basic/basic_renderer.js @@ -164,7 +164,7 @@ var BasicRenderer = AbstractRenderer.extend({ var recordWidgets = this.allFieldWidgets[record.id] || []; for (var i = 0 ; i < recordWidgets.length ; i++) { - var activated = recordWidgets[currentIndex].activate(); + var activated = recordWidgets[currentIndex].activate({event: options.event}); if (activated) { return currentIndex; } diff --git a/addons/web/static/src/js/views/form/form_renderer.js b/addons/web/static/src/js/views/form/form_renderer.js index e9d84ce1f5f..e23525d8fda 100644 --- a/addons/web/static/src/js/views/form/form_renderer.js +++ b/addons/web/static/src/js/views/form/form_renderer.js @@ -717,7 +717,7 @@ var FormRenderer = BasicRenderer.extend({ } }); if (focusWidget) { - focusWidget.activate(true); + focusWidget.activate({noselect: true}); } }, /** 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 65614e04983..49badb22f85 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 @@ -334,24 +334,31 @@ ListRenderer.include({ * * @param {integer} rowIndex * @param {integer} colIndex - * @param {boolean} [wrap=true] if true and no widget could be selected from - * the colIndex to the last column, then we wrap around and try to select - * a widget starting from the beginning + * @param {Object} [options] + * @param {Event} [options.event] original target of the event which + * @param {boolean} [options.wrap=true] if true and no widget could be + * triggered the cell selection + * selected from the colIndex to the last column, then we wrap around and + * try to select a widget starting from the beginning * @return {Deferred} fails if no cell could be selected */ - _selectCell: function (rowIndex, colIndex, wrap) { + _selectCell: function (rowIndex, colIndex, options) { // Do nothing if the user tries to select current cell if (rowIndex === this.currentRow && colIndex === this.currentCol) { return $.when(); } - wrap = wrap === undefined ? true : wrap; + var wrap = (!options || options.wrap === undefined) ? true : options.wrap; // Select the row then activate the widget in the correct cell var self = this; return this._selectRow(rowIndex).then(function () { var record = self.state.data[rowIndex]; var correctedIndex = colIndex - getNbButtonBefore(colIndex); - var fieldIndex = self._activateFieldWidget(record, correctedIndex, {inc: 1, wrap: wrap}); + var fieldIndex = self._activateFieldWidget(record, correctedIndex, { + inc: 1, + wrap: wrap, + event: options && options.event, + }); if (fieldIndex < 0) { return $.Deferred().reject(); @@ -474,7 +481,7 @@ ListRenderer.include({ var $tr = $td.parent(); var rowIndex = this.$('.o_data_row').index($tr); var colIndex = $tr.find('.o_data_cell').index($td); - this._selectCell(rowIndex, colIndex); + this._selectCell(rowIndex, colIndex, {event: event}); }, /** * We need to manually unselect row, because noone else would do it @@ -536,7 +543,7 @@ ListRenderer.include({ break; case 'previous': if (this.currentCol > 0) { - this._selectCell(this.currentRow, this.currentCol - 1, false) + this._selectCell(this.currentRow, this.currentCol - 1, {wrap: false}) .fail(this._moveToPreviousLine.bind(this)); } else { this._moveToPreviousLine(); @@ -544,7 +551,7 @@ ListRenderer.include({ break; case 'next': if (this.currentCol + 1 < this.columns.length) { - this._selectCell(this.currentRow, this.currentCol + 1, false) + this._selectCell(this.currentRow, this.currentCol + 1, {wrap: false}) .fail(this._moveToNextLine.bind(this)); } else { this._moveToNextLine(); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 6e007949ea7..04d0588bfab 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -237,10 +237,10 @@ QUnit.module('basic_fields', { assert.strictEqual(list.$('tbody td:not(.o_list_record_selector) .o_checkbox input:checked').length, 3, "should still have only 3 checked input"); - // Re-Edit the line to check the checkbox back + // Re-Edit the line to check the checkbox back but this time click on + // the checkbox directly in readonly mode ! $cell = list.$('tr.o_data_row:has(.o_checkbox input:not(:checked)) td:not(.o_list_record_selector)').first(); - $cell.click(); - $cell.find('.o_checkbox input:not(:checked)').click(); + $cell.find('.o_checkbox span').click(); // save list.$buttons.find('.o_form_button_save').click();