Skip to content

Commit 06cca64

Browse files
ContextMenu: find the item of a shown submenu by its element, not by the jQuery 1/2 context
$submenu.context exists only in jQuery 1.x and 2.x, so with the renderer and jQuery 3+ the submenus of the sibling items stayed shown on click.
1 parent 27891a9 commit 06cca64

2 files changed

Lines changed: 87 additions & 1 deletion

File tree

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import {
2+
afterEach, beforeEach, describe, expect, it, jest,
3+
} from '@jest/globals';
4+
import fx from '@js/common/core/animation/fx';
5+
import type { dxElementWrapper } from '@js/core/renderer';
6+
import $ from '@js/core/renderer';
7+
import type { Item } from '@js/ui/context_menu';
8+
import ContextMenu from '@ts/ui/context_menu/context_menu';
9+
10+
const ITEMS: Item[] = [{
11+
text: 'A',
12+
items: [
13+
{ text: 'A1', items: [{ text: 'A11' }] },
14+
{ text: 'A2', items: [{ text: 'A21' }] },
15+
],
16+
}, {
17+
text: 'B',
18+
items: [{ text: 'B1' }],
19+
}];
20+
21+
const instances: ContextMenu[] = [];
22+
23+
const createContextMenu = (): ContextMenu => {
24+
const $target = $('<div>').appendTo(document.body);
25+
const $element = $('<div>').appendTo(document.body);
26+
27+
const contextMenu = new ContextMenu($element.get(0) as HTMLElement, {
28+
target: $target.get(0),
29+
showSubmenuMode: 'onClick',
30+
items: ITEMS,
31+
});
32+
instances.push(contextMenu);
33+
34+
contextMenu.show().catch(() => {});
35+
jest.runAllTimers();
36+
37+
return contextMenu;
38+
};
39+
40+
describe('ContextMenu', () => {
41+
const getItem = (
42+
contextMenu: ContextMenu,
43+
text: string,
44+
): dxElementWrapper => $($(contextMenu._overlay?.$content())
45+
.find('.dx-menu-item')
46+
.toArray()
47+
.find((element) => $(element).children('.dx-menu-item-content').text() === text));
48+
49+
const isSubmenuVisible = (
50+
contextMenu: ContextMenu,
51+
text: string,
52+
): boolean => getItem(contextMenu, text)
53+
.children('.dx-submenu')
54+
.css('visibility') === 'visible';
55+
56+
beforeEach(() => {
57+
jest.useFakeTimers();
58+
fx.off = true;
59+
});
60+
61+
afterEach(() => {
62+
instances.forEach((instance) => instance.dispose());
63+
instances.length = 0;
64+
document.body.innerHTML = '';
65+
fx.off = false;
66+
jest.useRealTimers();
67+
});
68+
69+
describe('_hideAllShownChildSubmenus', () => {
70+
it('should hide the submenu of a sibling item when an item with a submenu is clicked', () => {
71+
const contextMenu = createContextMenu();
72+
contextMenu._showSubmenu(getItem(contextMenu, 'A'));
73+
contextMenu._showSubmenu(getItem(contextMenu, 'A2'));
74+
contextMenu._showSubmenu(getItem(contextMenu, 'A1'));
75+
jest.runAllTimers();
76+
77+
expect(isSubmenuVisible(contextMenu, 'A1')).toBe(true);
78+
79+
contextMenu._hideAllShownChildSubmenus(getItem(contextMenu, 'A2'));
80+
jest.runAllTimers();
81+
82+
expect(isSubmenuVisible(contextMenu, 'A1')).toBe(false);
83+
expect(isSubmenuVisible(contextMenu, 'A')).toBe(true);
84+
});
85+
});
86+
});

‎packages/devextreme/js/__internal/ui/context_menu/context_menu.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,7 @@ class ContextMenu<
772772

773773
if ($submenuElements.length > 0) {
774774
each(shownSubmenus, (index, $submenu) => {
775-
const $context = this._searchActiveItem($submenu.context).parent();
775+
const $context = this._searchActiveItem($submenu.get(0)).parent();
776776
if (
777777
$context.parent().is($clickedItem.parent().parent())
778778
&& !$context.is($clickedItem.parent())

0 commit comments

Comments
 (0)