Skip to content

Commit 3878990

Browse files
committed
TileTable: fix focus handling
The tile table should only show selection and menubar if the focus is inside the tile. This broke because the table data now has the focus and not the container. The change also fixes a bug, that was already there before the focus refactoring: When the table is focused and tab pressed, the focus went to the body instead of focusing the first menubar item. This happened because the menubar was made invisible as soon as focus left the table. Now, the menubar is only made invisible, when the focus leaves the tile, it may be on the table data, a menu bar item, a header item or the text filter. However, hiding the menubar cannot be done in the focusout handler because the menubar still has the focus. So it needs to be done later. RestoreFocusLater is the preferred method for such focus related actions to prevent flickering, see also comment in focusUtils.restoreFocusLater. 450639
1 parent 1a338d8 commit 3878990

File tree

2 files changed

+44
-34
lines changed

2 files changed

+44
-34
lines changed

eclipse-scout-core/src/tile/fields/tablefield/TileTableField.less

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2010, 2024 BSI Business Systems Integration AG
2+
* Copyright (c) 2010, 2026 BSI Business Systems Integration AG
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
@@ -42,9 +42,8 @@
4242
border-radius: 0;
4343
background-color: transparent;
4444

45-
&:focus,
46-
&.focused {
47-
box-shadow: none;
45+
&:has(.table-data:is(:focus, .focused)) {
46+
box-shadow: none !important;
4847
}
4948

5049
& > .table-header {
@@ -86,21 +85,21 @@
8685
}
8786
}
8887

89-
&:not(:focus):not(.focused) > .table-data > .table-row.selected {
90-
/* No selection color for non-focused table tiles */
91-
background-color: transparent;
92-
93-
&::after {
94-
border: 0;
95-
}
96-
}
97-
9888
& > .table-data {
9989
& + .scroll-shadow {
10090
.scroll-shadow.gradient();
10191
--scroll-shadow-color: var(--tile-background-color);
10292
}
10393

94+
&:not(:is(:focus, .focused)) > .table-row.selected {
95+
/* No selection color for non-focused table tiles */
96+
background-color: transparent;
97+
98+
&::after {
99+
border: 0;
100+
}
101+
}
102+
104103
& > .table-row {
105104
& > .table-cell,
106105
& > .table-cell > .font-icon {

eclipse-scout-core/src/tile/fields/tablefield/TileTableField.ts

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,41 @@
11
/*
2-
* Copyright (c) 2010, 2023 BSI Business Systems Integration AG
2+
* Copyright (c) 2010, 2026 BSI Business Systems Integration AG
33
*
44
* This program and the accompanying materials are made
55
* available under the terms of the Eclipse Public License 2.0
66
* which is available at https://www.eclipse.org/legal/epl-2.0/
77
*
88
* SPDX-License-Identifier: EPL-2.0
99
*/
10-
import {EventHandler, FormFieldTile, MenuBar, PropertyChangeEvent, TableField} from '../../../index';
10+
import {EventHandler, focusUtils, FormFieldTile, MenuBar, PropertyChangeEvent, TableField} from '../../../index';
1111
import $ from 'jquery';
1212

1313
export class TileTableField extends TableField {
14-
protected _tableBlurHandler: (event: JQuery.BlurEvent) => void;
15-
protected _tableFocusHandler: (event: JQuery.FocusEvent) => void;
1614
protected _menuBarPropertyChangeHandler: EventHandler<PropertyChangeEvent<any, MenuBar>>;
1715
protected _documentMouseDownHandler: (event: MouseEvent) => void;
1816

1917
constructor() {
2018
super();
2119

22-
this._tableBlurHandler = this._onTableBlur.bind(this);
23-
this._tableFocusHandler = this._onTableFocus.bind(this);
2420
this._menuBarPropertyChangeHandler = this._onMenuBarPropertyChange.bind(this);
2521
this._documentMouseDownHandler = this._onDocumentMouseDown.bind(this);
2622
}
2723

2824
protected override _render() {
2925
super._render();
26+
if ((this.parent as FormFieldTile).displayStyle !== FormFieldTile.DisplayStyle.DASHBOARD) {
27+
return;
28+
}
29+
3030
if (!this.session.focusManager.restrictedFocusGain) {
3131
this.$container.document(true).addEventListener('mousedown', this._documentMouseDownHandler, true);
3232
}
33+
this.$container
34+
.on('focusout', this._onTileFocusOut.bind(this))
35+
.on('focusin', this._onTileFocusIn.bind(this));
36+
if (!focusUtils.isOrHasActiveElement(this.$container)) {
37+
this._hideMenuBar(true);
38+
}
3339
}
3440

3541
protected override _remove() {
@@ -43,14 +49,8 @@ export class TileTableField extends TableField {
4349
return;
4450
}
4551
if (this.table) {
46-
this.table.$container
47-
.on('blur', this._tableBlurHandler)
48-
.on('focus', this._tableFocusHandler);
4952
this.table.menuBar.on('propertyChange', this._menuBarPropertyChangeHandler);
5053
this._toggleHasMenuBar();
51-
if (document.activeElement !== this.table.$container[0]) {
52-
this._hideMenuBar(true);
53-
}
5454
}
5555
}
5656

@@ -59,28 +59,39 @@ export class TileTableField extends TableField {
5959
return;
6060
}
6161
if (this.table) {
62-
this.table.$container
63-
.off('blur', this._tableBlurHandler)
64-
.off('focus', this._tableFocusHandler);
6562
this.table.menuBar.off('propertyChange', this._menuBarPropertyChangeHandler);
6663
}
6764
super._removeTable();
6865
}
6966

70-
protected _onTableBlur(event: JQuery.BlurEvent) {
67+
protected _onTileFocusOut(event: JQuery.FocusOutEvent) {
68+
if (this.$container.isOrHas(event.relatedTarget as Element)) {
69+
// If focus stays in tile, don't remove menubar
70+
return;
71+
}
7172
let popup = $('.popup').data('widget');
7273

73-
// hide menu bar if context menu popup is not attached to TileTableField
74-
if (!this.has(popup)) {
75-
this._hideMenuBar(true);
76-
}
74+
// Hide menu bar when focus leaves tile, but only if there is no popup open that belongs to the table (e.g. context menu or table header popup)
75+
// If a popup is open, the focus is on the popup but the menubar should still be visible
76+
requestAnimationFrame(() => {
77+
if (!this.rendered) {
78+
return;
79+
}
80+
81+
if (!this.has(popup)) {
82+
this._hideMenuBar(true);
83+
}
84+
});
7785
}
7886

79-
protected _onTableFocus(event: JQuery.FocusEvent) {
87+
protected _onTileFocusIn(event: JQuery.FocusInEvent) {
8088
this._hideMenuBar(false);
8189
}
8290

8391
protected _hideMenuBar(hiddenByUi: boolean) {
92+
if (!this.table) {
93+
return;
94+
}
8495
this.table.menuBar.hiddenByUi = hiddenByUi;
8596
this.table.menuBar.updateVisibility();
8697
}

0 commit comments

Comments
 (0)