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();