diff --git a/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js b/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js index dc65d2ea610..4913d5a6a80 100644 --- a/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js +++ b/addons/web/static/src/js/chrome/keyboard_navigation_mixin.js @@ -45,13 +45,21 @@ odoo.define('web.KeyboardNavigationMixin', function (require) { var accesskeyElements = $(document).find('[accesskey]').filter(':visible'); _.each(accesskeyElements, function (elem) { var overlay = $(_.str.sprintf("
%s
", $(elem).attr('accesskey').toUpperCase())); + + var $overlayParent; if (elem.tagName.toUpperCase() === "INPUT") { - // special case for the search input that has an access key defined. We cannot set the overlay on the input itself, only on its parent - overlay.appendTo($(elem).parent().css('position', 'relative')); + // special case for the search input that has an access key + // defined. We cannot set the overlay on the input itself, + // only on its parent. + $overlayParent = $(elem).parent(); + } else { + $overlayParent = $(elem); } - else { - overlay.appendTo($(elem).css('position', 'relative')); + + if ($overlayParent.css('position') !== 'absolute') { + $overlayParent.css('position', 'relative'); } + overlay.appendTo($overlayParent); }); }, /** diff --git a/addons/web/static/tests/chrome/keyboard_navigation_mixin_tests.js b/addons/web/static/tests/chrome/keyboard_navigation_mixin_tests.js index 38f13e7a117..e26451cd268 100644 --- a/addons/web/static/tests/chrome/keyboard_navigation_mixin_tests.js +++ b/addons/web/static/tests/chrome/keyboard_navigation_mixin_tests.js @@ -2,6 +2,7 @@ odoo.define('web.keyboard_navigation_mixin_tests', function (require) { "use strict"; var KeyboardNavigationMixin = require('web.KeyboardNavigationMixin'); +var testUtils = require('web.test_utils'); var Widget = require('web.Widget'); QUnit.module('KeyboardNavigationMixin', function () { @@ -16,7 +17,8 @@ QUnit.module('KeyboardNavigationMixin', function () { return this._super.apply(this, arguments); }, }); - var w = new KeyboardWidget(); + var parent = testUtils.createParent({}); + var w = new KeyboardWidget(parent); w.appendTo($target); // minimum set of attribute to generate a native event that works with the mixin @@ -26,6 +28,43 @@ QUnit.module('KeyboardNavigationMixin', function () { w.$el[0].dispatchEvent(e); assert.ok(w.$el.find('button[aria-keyshortcuts]')[0], 'the aria-keyshortcuts is set on the button'); + + parent.destroy(); + }); + + QUnit.test('keep CSS position absolute for parent of overlay', function (assert) { + // If we change the CSS position of an 'absolute' element to 'relative', + // we may likely change its position on the document. Since the overlay + // CSS position is 'absolute', it will match the size and cover the + // parent with 'absolute' > 'absolute', without altering the position + // of the parent on the document. + assert.expect(1); + var $target = $('#qunit-fixture'); + var $button; + var KeyboardWidget = Widget.extend(KeyboardNavigationMixin, { + start: function () { + $button = $('