diff --git a/addons/web/static/src/js/fields/basic_fields.js b/addons/web/static/src/js/fields/basic_fields.js index 553a79cad20..7ef6a10368d 100644 --- a/addons/web/static/src/js/fields/basic_fields.js +++ b/addons/web/static/src/js/fields/basic_fields.js @@ -595,6 +595,10 @@ var LinkButton = AbstractField.extend({ var FieldDateRange = InputField.extend({ className: 'o_field_date_range', + events: Object.assign({}, InputField.prototype.events, { + 'show.daterangepicker': '_onDateRangePickerShow', + 'hide.daterangepicker': '_onDateRangePickerHide', + }), tagName: 'span', jsLibs: [ '/web/static/lib/daterangepicker/daterangepicker.js', @@ -633,6 +637,9 @@ var FieldDateRange = InputField.extend({ if (this.$pickerContainer) { this.$pickerContainer.remove(); } + if (this._onScroll) { + window.removeEventListener('scroll', this._onScroll, true); + } this._super.apply(this, arguments); }, @@ -711,6 +718,34 @@ var FieldDateRange = InputField.extend({ ev.stopPropagation(); }); }, + + //-------------------------------------------------------------------------- + // Handlers + //-------------------------------------------------------------------------- + + /** + * Unbind the scroll event handler when the daterangepicker is closed. + * + * @private + */ + _onDateRangePickerHide() { + if (this._onScroll) { + window.removeEventListener('scroll', this._onScroll, true); + } + }, + /** + * Bind the scroll event handle when the daterangepicker is open. + * + * @private + */ + _onDateRangePickerShow() { + this._onScroll = ev => { + if (ev.target !== this.$el.data('daterangepicker').element.get(0)) { + this.$el.data('daterangepicker').hide(); + } + }; + window.addEventListener('scroll', this._onScroll, true); + }, }); var FieldDate = InputField.extend({ diff --git a/addons/web/static/src/js/libs/daterangepicker.js b/addons/web/static/src/js/libs/daterangepicker.js index 4d4acfeb2b9..dd731eb4cee 100644 --- a/addons/web/static/src/js/libs/daterangepicker.js +++ b/addons/web/static/src/js/libs/daterangepicker.js @@ -11,4 +11,14 @@ daterangepicker.prototype.clickDate = function (ev) { } }; +/** + * Override to open up or down based on top/bottom space in window. + */ +const moveFunction = daterangepicker.prototype.move; +daterangepicker.prototype.move = function () { + const offset = this.element.offset(); + this.drops = this.container.height() < offset.top ? 'up' : 'down'; + moveFunction.apply(this, arguments); +}; + }); diff --git a/addons/web/static/tests/fields/basic_fields_tests.js b/addons/web/static/tests/fields/basic_fields_tests.js index 7af27167e4c..5f537db41eb 100644 --- a/addons/web/static/tests/fields/basic_fields_tests.js +++ b/addons/web/static/tests/fields/basic_fields_tests.js @@ -3325,6 +3325,35 @@ QUnit.module('basic_fields', { form.destroy(); }); + QUnit.test('daterangepicker should disappear on scrolling outside of it', async function (assert) { + assert.expect(2); + + this.data.partner.fields.datetime_end = {string: 'Datetime End', type: 'datetime'}; + this.data.partner.records[0].datetime_end = '2017-03-13 00:00:00'; + + const form = await createView({ + View: FormView, + model: 'partner', + data: this.data, + arch: ` +
`, + res_id: 1, + }); + + await testUtils.form.clickEdit(form); + await testUtils.dom.click(form.$('.o_field_date_range:first')); + + assert.isVisible($('.daterangepicker:first'), "date range picker should be opened"); + + form.el.dispatchEvent(new Event('scroll')); + assert.isNotVisible($('.daterangepicker:first'), "date range picker should be closed"); + + form.destroy(); + }); + QUnit.module('FieldDate'); QUnit.test('date field: toggle datepicker [REQUIRE FOCUS]', async function (assert) {