From c04b840a45edd222c50e74d18e2d02a3dd3175cd Mon Sep 17 00:00:00 2001 From: Aaron Bohy Date: Fri, 5 May 2017 15:21:36 +0200 Subject: [PATCH] [FIX] web: FieldMonetary: don't loose focus after edition ... in x2many editable list views. Field widgets can detect that they are at the origin of a field_changed event, so that they don't re-render themselves when they are being edited. This didn't work for fields inside x2many list views. This wasn't a big problem for most of the fields, because the cursor position was automatically reset after a re-rendering, but it wasn't working for monetary fields that empty their $el before each re-rendering. This rev. fixes the issue by making the field widgets inside x2many list able to detect that they are the origin of a change, and thus removes the now useless code that restore the cursor position. --- .../web/static/src/js/fields/basic_fields.js | 5 -- .../static/src/js/fields/relational_fields.js | 9 ++- .../static/tests/fields/basic_fields_tests.js | 65 ++++++++++++++++++- 3 files changed, 71 insertions(+), 8 deletions(-) diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index b3defa97911..fc4af105865 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -229,12 +229,7 @@ var InputField = DebouncedField.extend({ type: 'text', placeholder: this.attrs.placeholder || "", }); - // Save cursor position to restore it after updating value - var selectionStart = this.$input[0].selectionStart; - var selectionEnd = this.$input[0].selectionEnd; this.$input.val(this._formatValue(this.value)); - this.$input[0].selectionStart = selectionStart; - this.$input[0].selectionEnd = selectionEnd; return this.$input; }, /** diff --git a/addons/web/static/src/js/fields/relational_fields.js b/addons/web/static/src/js/fields/relational_fields.js index e9fa7dd09d1..db2db031a15 100644 --- a/addons/web/static/src/js/fields/relational_fields.js +++ b/addons/web/static/src/js/fields/relational_fields.js @@ -600,7 +600,7 @@ var FieldX2Many = AbstractField.extend({ if (command.operation === 'UPDATE') { var state = record.data[this.name]; var fieldNames = state.getFieldNames(); - this.renderer.confirmChange(state, command.id, fieldNames); + this.renderer.confirmChange(state, command.id, fieldNames, ev.initialEvent); return $.when(); } } @@ -787,12 +787,19 @@ var FieldX2Many = AbstractField.extend({ */ _onFieldChanged: function (ev) { if (ev.target === this) { + ev.initialEvent = this.lastInitialEvent; return; } ev.stopPropagation(); // changes occured in an editable list var changes = ev.data.changes; + // save the initial event triggering the field_changed, as it will be + // necessary when the field triggering this event will be reset (to + // prevent it from re-rendering itself, formatting its value, loosing + // the focus... while still being edited) + this.lastInitialEvent = undefined; if (Object.keys(changes).length) { + this.lastInitialEvent = ev; this._setValue({ operation: 'UPDATE', id: ev.data.dataPointID, diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 72a9e61f3f5..f2334b61f4a 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -1144,9 +1144,9 @@ QUnit.module('basic_fields', { var evt = document.createEvent("MouseEvents"); //taken ref from https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent evt.initMouseEvent("mouseover", true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); - $('.discreteBar')[0].dispatchEvent(evt) + $('.discreteBar')[0].dispatchEvent(evt); var tooltip = $('.nvtooltip').find('table').find('.key')[0].innerText; - assert.equal(tooltip,graph_key, "graph tooltip should be generated ") + assert.equal(tooltip,graph_key, "graph tooltip should be generated "); $('.nvtooltip').remove(); // force a re-rendering of the first record (to check if the @@ -1736,6 +1736,67 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('should keep the focus when being edited in x2many lists', function (assert) { + assert.expect(6); + + this.data.partner.fields.currency_id.default = 1; + this.data.partner.fields.m2m = { + string: "m2m", type: "many2many", relation: 'partner', default: [[6, false, [2]]], + }; + var form = createView({ + View: FormView, + model: 'partner', + data: this.data, + arch:'
' + + '' + + '' + + '' + + '' + + '
', + archs: { + 'partner,false,list': '' + + '' + + '' + + '', + }, + session: { + currencies: _.indexBy(this.data.currency.records, 'id'), + }, + }); + + // test the monetary field inside the one2many + var $o2m = form.$('.o_field_widget[name=p]'); + $o2m.find('.o_field_x2many_list_row_add a').click(); + $o2m.find('.o_field_widget input').val("22").trigger('input'); + + assert.strictEqual($o2m.find('.o_field_widget input').get(0), document.activeElement, + "the focus should still be on the input"); + assert.strictEqual($o2m.find('.o_field_widget input').val(), "22", + "the value should not have been formatted yet"); + + form.$el.click(); // focusout the input + + assert.strictEqual($o2m.find('.o_field_widget[name=qux]').html(), "$ 22.00", + "the value should have been formatted after losing the focus"); + + // test the monetary field inside the many2many + var $m2m = form.$('.o_field_widget[name=m2m]'); + $m2m.find('.o_data_row td:first').click(); + $m2m.find('.o_field_widget input').val("22").trigger('input'); + + assert.strictEqual($m2m.find('.o_field_widget input').get(0), document.activeElement, + "the focus should still be on the input"); + assert.strictEqual($m2m.find('.o_field_widget input').val(), "22", + "the value should not have been formatted yet"); + + form.$el.click(); // focusout the input + + assert.strictEqual($m2m.find('.o_field_widget[name=qux]').html(), "22.00 €", + "the value should have been formatted after losing the focus"); + + form.destroy(); + }); + QUnit.module('FieldInteger'); QUnit.test('integer field when unset', function (assert) {