@eclipse-scout/core 22.0.2 → 22.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/eclipse-scout-core-af5ff6abad5f1ff9fd18.min.js +2 -0
  2. package/dist/eclipse-scout-core-af5ff6abad5f1ff9fd18.min.js.map +1 -0
  3. package/dist/eclipse-scout-core-theme-74b63e0d57bed407a729.min.css +1 -0
  4. package/dist/eclipse-scout-core-theme-dark-b82aea152f416e38ce7f.min.css +1 -0
  5. package/dist/eclipse-scout-core-theme-dark.css +153 -52
  6. package/dist/eclipse-scout-core-theme-dark.css.map +1 -1
  7. package/dist/eclipse-scout-core-theme.css +153 -52
  8. package/dist/eclipse-scout-core-theme.css.map +1 -1
  9. package/dist/eclipse-scout-core.js +785 -564
  10. package/dist/eclipse-scout-core.js.map +1 -1
  11. package/dist/file-list +4 -4
  12. package/package.json +2 -2
  13. package/src/ErrorHandler.js +66 -28
  14. package/src/{table/TableHeaderMenuButtonKeyStroke.js → action/ActionExecKeyStroke.js} +4 -5
  15. package/src/box/Box.less +10 -6
  16. package/src/breadcrumbbar/BreadcrumbItem.less +3 -6
  17. package/src/checkbox/CheckBox.less +3 -1
  18. package/src/datepicker/DatePickerTouchPopup.js +8 -0
  19. package/src/desktop/DisableBrowserF5ReloadKeyStroke.js +1 -0
  20. package/src/desktop/bench/DesktopTabSelectKeyStroke.js +2 -1
  21. package/src/desktop/desktoptab/DisableBrowserTabSwitchingKeyStroke.js +1 -0
  22. package/src/desktop/navigation/EnlargeNavigationKeyStroke.js +1 -0
  23. package/src/desktop/navigation/ShrinkNavigationKeyStroke.js +1 -0
  24. package/src/desktop/viewbutton/ViewMenuPopupEnterKeyStroke.js +2 -1
  25. package/src/filechooser/FileChooser.js +1 -1
  26. package/src/filechooser/FileChooser.less +15 -10
  27. package/src/focus/FocusContext.js +11 -8
  28. package/src/focus/FocusManager.js +24 -5
  29. package/src/form/fields/LookupBox.js +3 -1
  30. package/src/form/fields/LookupBox.less +28 -2
  31. package/src/form/fields/TextFieldIcon.less +2 -2
  32. package/src/form/fields/ValueField.js +11 -2
  33. package/src/form/fields/breadcrumbbarfield/BreadcrumbBarField.less +10 -4
  34. package/src/form/fields/button/ButtonKeyStroke.js +0 -3
  35. package/src/form/fields/datefield/DateField.js +31 -47
  36. package/src/form/fields/filechooserfield/FileChooserFieldBrowseKeyStroke.js +1 -3
  37. package/src/form/fields/filechooserfield/FileChooserFieldDeleteKeyStroke.js +1 -3
  38. package/src/form/fields/groupbox/GroupBox.js +1 -0
  39. package/src/form/fields/listbox/ListBox.js +5 -4
  40. package/src/form/fields/lookupfield/lookupField.js +6 -5
  41. package/src/form/fields/smartfield/ProposalField.js +2 -1
  42. package/src/form/fields/smartfield/ProposalTreeNode.js +4 -8
  43. package/src/form/fields/smartfield/SmartField.js +4 -20
  44. package/src/form/fields/smartfield/SmartField.less +24 -11
  45. package/src/form/fields/splitbox/SplitBoxCollapseKeyStroke.js +1 -0
  46. package/src/form/fields/splitbox/SplitBoxFirstCollapseKeyStroke.js +1 -0
  47. package/src/form/fields/splitbox/SplitBoxSecondCollapseKeyStroke.js +1 -0
  48. package/src/form/fields/tabbox/TabAreaLeftKeyStroke.js +2 -0
  49. package/src/form/fields/tabbox/TabAreaRightKeyStroke.js +2 -0
  50. package/src/form/fields/tabbox/TabBox.js +4 -0
  51. package/src/form/fields/tabbox/TabBoxHeader.js +4 -0
  52. package/src/form/fields/tabbox/TabItem.js +4 -0
  53. package/src/form/fields/treebox/TreeBox.js +6 -5
  54. package/src/index.js +1 -1
  55. package/src/jquery/jquery-scout.js +12 -0
  56. package/src/keystroke/CloseKeyStroke.js +1 -0
  57. package/src/keystroke/ContextMenuKeyStroke.js +1 -0
  58. package/src/keystroke/FocusFilterFieldKeyStroke.js +1 -0
  59. package/src/keystroke/KeyStroke.js +11 -3
  60. package/src/keystroke/TabItemKeyStroke.js +8 -5
  61. package/src/logging/logging.js +16 -8
  62. package/src/login/LoginBox.js +3 -2
  63. package/src/login/LoginBox.less +18 -1
  64. package/src/menu/MenuExecKeyStroke.js +3 -17
  65. package/src/menu/MenuNavigationKeyStroke.js +1 -0
  66. package/src/menu/menubar/MenuBarLeftKeyStroke.js +2 -0
  67. package/src/menu/menubar/MenuBarRightKeyStroke.js +2 -0
  68. package/src/messagebox/MessageBox.less +17 -17
  69. package/src/planner/Planner.js +2 -0
  70. package/src/session/Session.js +8 -5
  71. package/src/style/fonts.less +5 -1
  72. package/src/style/sizes.less +14 -5
  73. package/src/table/Table.js +25 -19
  74. package/src/table/Table.less +14 -7
  75. package/src/table/TableAdapter.js +9 -12
  76. package/src/table/TableHeaderMenuButton.js +2 -2
  77. package/src/table/TableLayout.js +6 -0
  78. package/src/table/columns/Column.js +8 -5
  79. package/src/table/columns/ColumnOptimalWidthMeasurer.js +1 -1
  80. package/src/table/editor/CellEditorPopup.js +21 -14
  81. package/src/table/keystrokes/AbstractTableNavigationKeyStroke.js +1 -0
  82. package/src/table/keystrokes/TableCopyKeyStroke.js +1 -0
  83. package/src/table/keystrokes/TableNavigationCollapseKeyStroke.js +2 -2
  84. package/src/table/keystrokes/TableNavigationEndKeyStroke.js +2 -2
  85. package/src/table/keystrokes/TableNavigationExpandKeyStroke.js +2 -2
  86. package/src/table/keystrokes/TableNavigationHomeKeyStroke.js +2 -2
  87. package/src/table/keystrokes/TableNavigationPageDownKeyStroke.js +2 -2
  88. package/src/table/keystrokes/TableNavigationPageUpKeyStroke.js +2 -2
  89. package/src/table/keystrokes/TableNavigationUpKeyStroke.js +2 -2
  90. package/src/table/keystrokes/TableRefreshKeyStroke.js +2 -2
  91. package/src/table/keystrokes/TableSelectAllKeyStroke.js +3 -2
  92. package/src/table/keystrokes/TableStartCellEditKeyStroke.js +2 -2
  93. package/src/testing/index.js +1 -0
  94. package/src/testing/lookup/AbortableMicrotaskStaticLookupCall.js +50 -0
  95. package/src/tile/TileGrid.js +9 -11
  96. package/src/tile/fields/tablefield/TileTableField.less +19 -2
  97. package/src/tile/keystrokes/TileGridSelectKeyStroke.js +3 -2
  98. package/src/timepicker/TimePickerTouchPopup.js +8 -0
  99. package/src/tree/Tree.js +8 -4
  100. package/src/tree/Tree.less +12 -2
  101. package/src/tree/keystrokes/AbstractTreeNavigationKeyStroke.js +1 -0
  102. package/src/tree/keystrokes/TreeCollapseAllKeyStroke.js +2 -2
  103. package/src/tree/keystrokes/TreeExpandOrDrillDownKeyStroke.js +2 -2
  104. package/src/tree/keystrokes/TreeNavigationDownKeyStroke.js +2 -2
  105. package/src/tree/keystrokes/TreeNavigationEndKeyStroke.js +2 -2
  106. package/src/tree/keystrokes/TreeNavigationUpKeyStroke.js +2 -2
  107. package/src/util/Device.js +4 -4
  108. package/src/util/arrays.js +20 -0
  109. package/src/widget/Widget.js +6 -4
  110. package/dist/eclipse-scout-core-c98fb5230e71dcec75ce.min.js +0 -2
  111. package/dist/eclipse-scout-core-c98fb5230e71dcec75ce.min.js.map +0 -1
  112. package/dist/eclipse-scout-core-theme-6b2fef56e9e49231a49c.min.css +0 -1
  113. package/dist/eclipse-scout-core-theme-dark-d2bb274dd42f132bfca0.min.css +0 -1
@@ -12,9 +12,16 @@ import {NullLogger, scout, URL} from '../index';
12
12
  import $ from 'jquery';
13
13
  import strings from '../util/strings';
14
14
 
15
- /* global log4javascript */
15
+ const Level = {
16
+ TRACE: 'trace',
17
+ DEBUG: 'debug',
18
+ INFO: 'info',
19
+ WARN: 'warn',
20
+ ERROR: 'error',
21
+ FATAL: 'fatal'
22
+ };
16
23
 
17
- const DEFAULT_LEVEL = 'trace';
24
+ const DEFAULT_LEVEL = Level.TRACE;
18
25
  let initialized = false;
19
26
  let _appendersToAdd = [];
20
27
  let showStackTraces = true;
@@ -85,17 +92,17 @@ export function parseLevel(level) {
85
92
  }
86
93
  level = level.toLowerCase();
87
94
  switch (level) {
88
- case 'trace':
95
+ case Level.TRACE:
89
96
  return log4javascript.Level.TRACE;
90
- case 'debug':
97
+ case Level.DEBUG:
91
98
  return log4javascript.Level.DEBUG;
92
- case 'info':
99
+ case Level.INFO:
93
100
  return log4javascript.Level.INFO;
94
- case 'warn':
101
+ case Level.WARN:
95
102
  return log4javascript.Level.WARN;
96
- case 'error':
103
+ case Level.ERROR:
97
104
  return log4javascript.Level.ERROR;
98
- case 'fatal':
105
+ case Level.FATAL:
99
106
  return log4javascript.Level.FATAL;
100
107
  }
101
108
  }
@@ -115,6 +122,7 @@ export function addAppender(factoryName, options) {
115
122
 
116
123
  export default {
117
124
  DEFAULT_LEVEL,
125
+ Level,
118
126
  addAppender,
119
127
  bootstrap,
120
128
  initLog4Javascript,
@@ -1,9 +1,9 @@
1
1
  /*
2
- * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
6
- * http://www.eclipse.org/legal/epl-v10.html
6
+ * https://www.eclipse.org/legal/epl-v10.html
7
7
  *
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
@@ -56,6 +56,7 @@ export default class LoginBox extends Box {
56
56
  if (this.messageKey) {
57
57
  this.$message = $('<div>')
58
58
  .attr('id', 'message-box')
59
+ .addClass('message-box')
59
60
  .html(strings.nl2br(this.texts.get(this.messageKey)))
60
61
  .appendTo(this.$form);
61
62
  }
@@ -3,7 +3,7 @@
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
6
- * http://www.eclipse.org/legal/epl-v10.html
6
+ * https://www.eclipse.org/legal/epl-v10.html
7
7
  *
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
@@ -19,6 +19,11 @@
19
19
 
20
20
  & > .button {
21
21
  margin-top: 16px;
22
+ margin-bottom: 0;
23
+ }
24
+
25
+ & > .message-box {
26
+ margin: 0 20px 12px 20px;
22
27
  }
23
28
 
24
29
  & > input.alternative:-webkit-autofill {
@@ -93,3 +98,15 @@
93
98
  #scout.animation(nop 0.05s);
94
99
  }
95
100
  }
101
+
102
+ @media (max-width: @box-responsive-width) {
103
+ .login-box-content > form {
104
+ & > .message-box,
105
+ & > input,
106
+ & > .button {
107
+ width: 100%;
108
+ margin-left: 0;
109
+ margin-right: 0;
110
+ }
111
+ }
112
+ }
@@ -8,26 +8,12 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
- import {keys, KeyStroke} from '../index';
11
+ import {ActionExecKeyStroke} from '../index';
12
12
 
13
- export default class MenuExecKeyStroke extends KeyStroke {
13
+ export default class MenuExecKeyStroke extends ActionExecKeyStroke {
14
14
 
15
15
  constructor(menu) {
16
- super();
17
- this.field = menu;
18
- this.which = [keys.SPACE, keys.ENTER];
19
- this.stopPropagation = true;
20
-
16
+ super(menu);
21
17
  this.renderingHints.offset = 16;
22
- this.renderingHints.$drawingArea = function($drawingArea, event) {
23
- return this.field.$container;
24
- }.bind(this);
25
- }
26
-
27
- /**
28
- * @override KeyStroke.js
29
- */
30
- handle(event) {
31
- this.field.doAction();
32
18
  }
33
19
  }
@@ -15,6 +15,7 @@ export default class MenuNavigationKeyStroke extends KeyStroke {
15
15
  constructor(popup) {
16
16
  super();
17
17
  this.field = popup;
18
+ this.inheritAccessibility = false;
18
19
  }
19
20
 
20
21
  _accept(event) {
@@ -12,6 +12,7 @@ import {keys, KeyStroke} from '../../index';
12
12
 
13
13
  export default class MenuBarLeftKeyStroke extends KeyStroke {
14
14
 
15
+ // noinspection DuplicatedCode
15
16
  constructor(menuBar) {
16
17
  super();
17
18
  this.field = menuBar;
@@ -19,6 +20,7 @@ export default class MenuBarLeftKeyStroke extends KeyStroke {
19
20
  this.renderingHints.render = false;
20
21
  this.stopPropagation = true;
21
22
  this.keyStrokeMode = KeyStroke.Mode.DOWN;
23
+ this.inheritAccessibility = false;
22
24
  }
23
25
 
24
26
  handle(event) {
@@ -12,6 +12,7 @@ import {keys, KeyStroke} from '../../index';
12
12
 
13
13
  export default class MenuBarRightKeyStroke extends KeyStroke {
14
14
 
15
+ // noinspection DuplicatedCode
15
16
  constructor(menuBar) {
16
17
  super();
17
18
  this.field = menuBar;
@@ -19,6 +20,7 @@ export default class MenuBarRightKeyStroke extends KeyStroke {
19
20
  this.renderingHints.render = false;
20
21
  this.stopPropagation = true;
21
22
  this.keyStrokeMode = KeyStroke.Mode.DOWN;
23
+ this.inheritAccessibility = false;
22
24
  }
23
25
 
24
26
  handle(event) {
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2010-2021 BSI Business Systems Integration AG.
2
+ * Copyright (c) 2010-2022 BSI Business Systems Integration AG.
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
@@ -22,6 +22,22 @@
22
22
  border-radius: 0;
23
23
  }
24
24
 
25
+ &.full-width {
26
+ & > .messagebox-buttons {
27
+ padding-left: 10px;
28
+ padding-right: 10px;
29
+
30
+ & > .box-button {
31
+ min-width: 70px; /* less min width for buttons on small screens */
32
+ margin-right: 8px;
33
+
34
+ &:last-child {
35
+ margin-right: 0;
36
+ }
37
+ }
38
+ }
39
+ }
40
+
25
41
  .severity-button(@color, @hover-color: darken(@color, 6%), @active-color: darken(@color, 13%), @focus-color: @focus-box-shadow-color) {
26
42
  & > .box-buttons > .box-button {
27
43
  border-color: @color;
@@ -225,23 +241,7 @@
225
241
 
226
242
  @media (max-width: @messagebox-max-width) {
227
243
  .messagebox {
228
- /* reduce message box width on small screens */
229
- max-width: 330px;
230
244
  /* no need to have a margin on small screens */
231
245
  margin: 0;
232
-
233
- & > .messagebox-buttons {
234
- padding-left: 10px;
235
- padding-right: 10px;
236
-
237
- & > .box-button {
238
- min-width: 70px; /* less min width for buttons on small screens */
239
- margin-right: 8px;
240
-
241
- &:last-child {
242
- margin-right: 0;
243
- }
244
- }
245
- }
246
246
  }
247
247
  }
@@ -1533,6 +1533,8 @@ export default class Planner extends Widget {
1533
1533
  this._renderViewRange();
1534
1534
  this._rerenderActivities();
1535
1535
  this._renderSelectedActivity();
1536
+ this.validateLayoutTree(); // Layouting is required for adjusting the scroll position
1537
+ this._reconcileScrollPos();
1536
1538
  }
1537
1539
  }
1538
1540
 
@@ -8,7 +8,7 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
- import {AjaxCall, App, arrays, BackgroundJobPollingStatus, BackgroundJobPollingSupport, Device, EventSupport, FileInput, files as fileUtil, FocusManager, fonts, icons, LayoutValidator, Locale, MessageBox, ModelAdapter, NullWidget, ObjectFactory, objects, Reconnector, RemoteEvent, ResponseQueue, scout, Status, strings, TextMap, texts, TypeDescriptor, URL, UserAgent, webstorage} from '../index';
11
+ import {AjaxCall, App, arrays, BackgroundJobPollingStatus, BackgroundJobPollingSupport, Device, EventSupport, FileInput, files as fileUtil, FocusManager, fonts, icons, LayoutValidator, Locale, logging, MessageBox, ModelAdapter, NullWidget, ObjectFactory, objects, Reconnector, RemoteEvent, ResponseQueue, scout, Status, strings, TextMap, texts, TypeDescriptor, URL, UserAgent, webstorage} from '../index';
12
12
  import $ from 'jquery';
13
13
 
14
14
  export default class Session {
@@ -1364,13 +1364,16 @@ export default class Session {
1364
1364
  }
1365
1365
 
1366
1366
  /**
1367
- * Sends a request containing the error message for logging purpose.
1368
- * The request is sent immediately (does not await pending requests)
1367
+ * Sends a request containing the log message for logging purpose.
1368
+ * The request is sent immediately (does not await pending requests).
1369
+ * @param {string} message the log message
1370
+ * @param {logging.Level} [level] the log level used to log the message. Default is {@link logging.Level.ERROR}.
1369
1371
  */
1370
- sendLogRequest(message) {
1372
+ sendLogRequest(message, level) {
1371
1373
  let request = this._newRequest({
1372
1374
  log: true,
1373
- message: message
1375
+ message: message,
1376
+ level: scout.nvl(level, logging.Level.ERROR)
1374
1377
  });
1375
1378
  if (this.currentEvent) {
1376
1379
  request.event = {
@@ -33,6 +33,7 @@ Try these to switch between fonts:
33
33
  @font-size-large: 16px;
34
34
  @font-size-extra-large: 32px;
35
35
 
36
+ @font-size-icon-small: 14px;
36
37
  @font-size-icon: 16px;
37
38
  @font-size-icon-large: 24px;
38
39
 
@@ -43,8 +44,11 @@ Try these to switch between fonts:
43
44
  // or are often placed to the side of widgets with icons
44
45
  @text-margin-top: 1px;
45
46
 
46
- @icon-font-weight-light: 300;
47
+ // Icons aligned with line-height may use this variable.
48
+ // It should have the same size as regular text (not the font-size, the actual size)
49
+ @font-icon-line-height: 15px;
47
50
 
51
+ @icon-font-weight-light: 300;
48
52
  @tooltip-font-weight: @font-weight-normal;
49
53
 
50
54
  @font-face {
@@ -3,7 +3,7 @@
3
3
  * All rights reserved. This program and the accompanying materials
4
4
  * are made available under the terms of the Eclipse Public License v1.0
5
5
  * which accompanies this distribution, and is available at
6
- * http://www.eclipse.org/legal/epl-v10.html
6
+ * https://www.eclipse.org/legal/epl-v10.html
7
7
  *
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
@@ -17,6 +17,8 @@
17
17
  @border-radius-medium: 8px;
18
18
  @border-radius-large: 12px;
19
19
  @borderless-field-padding-y: @text-field-padding-y + 1px;
20
+ @breadcrumb-bar-field-padding-bottom: 0;
21
+ @breadcrumb-bar-field-padding-bottom-dense: 4px;
20
22
  @collapse-handle-border-radius: @border-radius-medium;
21
23
  @control-border-radius: @border-radius;
22
24
  @control-alternative-border-radius: @control-border-radius;
@@ -173,7 +175,7 @@
173
175
  @desktop-tab-border-radius: @view-tab-selected-border-radius;
174
176
  @desktop-tab-margin-top: @view-tab-selected-margin-top;
175
177
  @desktop-tool-box-item-border-radius: @view-tab-border-radius;
176
- @desktop-tool-box-item-font-size: 14px;
178
+ @desktop-tool-box-item-font-size: @font-size-icon-small;
177
179
  @desktop-tool-box-item-margin: 3px;
178
180
  @desktop-tool-box-item-margin-top: @view-tab-margin-top;
179
181
  @detail-table-border-radius: 4px;
@@ -236,7 +238,7 @@
236
238
  @outline-node-control-padding-left: @outline-title-padding-left;
237
239
  @outline-node-control-padding-y: @outline-node-padding-y;
238
240
  @outline-node-control-line-height: @tree-node-control-line-height;
239
- @outline-node-font-icon-line-height: 14px;
241
+ @outline-node-font-icon-line-height: @tree-node-font-icon-line-height;
240
242
  @outline-node-font-icon-size: 16px;
241
243
  @outline-node-padding-left: 37px;
242
244
  @outline-node-padding-right: 8px;
@@ -291,9 +293,15 @@
291
293
  @tab-item-title-padding-bottom: @group-box-title-padding-bottom;
292
294
  @tab-item-title-padding-top: @group-box-title-padding-top;
293
295
  @tab-item-title-margin-top: @group-box-header-margin-top;
296
+ @table-aggregate-cell-font-icon-line-height: 14px;
297
+ @table-aggregate-sum-avg-font-icon-size: 13px;
298
+ @table-aggregate-min-max-font-icon-size: 15px;
299
+ @table-aggregate-row-font-size: @font-size-smaller;
294
300
  @table-cell-padding-left: 10px;
295
301
  @table-cell-padding-right: @table-cell-padding-left;
296
302
  @table-cell-padding-right-last: @scrollbar-size;
303
+ @table-cell-font-icon-size: @tree-node-font-icon-size;
304
+ @table-cell-font-icon-line-height: @tree-node-font-icon-line-height;
297
305
  @table-control-content-padding: 10px;
298
306
  @table-control-container-height: 364px;
299
307
  @table-control-container-height-dense: 320px;
@@ -349,9 +357,10 @@
349
357
  @tree-node-checkbox-margin-top: -2px;
350
358
  @tree-node-control-checkbox-size: 20px + @tree-node-control-size;
351
359
  @tree-node-control-size: 16px;
352
- @tree-node-control-line-height: 14px;
360
+ @tree-node-control-line-height: @font-icon-line-height;
353
361
  @tree-node-control-padding-left: 13px;
354
- @tree-node-font-icon-line-height: 15px;
362
+ @tree-node-font-icon-line-height: @font-icon-line-height;
363
+ @tree-node-font-icon-size: @font-size-icon-small;
355
364
  @tree-node-padding-left: 28px;
356
365
  @tree-node-padding-right: 7px;
357
366
  @tree-node-padding-y: 7px;
@@ -555,7 +555,7 @@ export default class Table extends Widget {
555
555
  return; // row was removed while loading the image
556
556
  }
557
557
  let oldRowHeight = row.height;
558
- row.height = $row.outerHeight(true);
558
+ row.height = this._measureRowHeight($row);
559
559
  if (oldRowHeight !== row.height) {
560
560
  this.invalidateLayoutTree();
561
561
  }
@@ -1528,12 +1528,12 @@ export default class Table extends Widget {
1528
1528
 
1529
1529
  _updateRowHeight() {
1530
1530
  let $emptyRow = this.$data.appendDiv('table-row');
1531
- let $emptyAggrRow = this.$data.appendDiv('table-aggregate-row');
1531
+ let $emptyAggrRow = this._build$AggregateRow().appendTo(this.$data);
1532
1532
 
1533
1533
  $emptyRow.appendDiv('table-cell').html('&nbsp;');
1534
- $emptyAggrRow.appendDiv('table-cell').html('&nbsp;');
1535
- this.rowHeight = $emptyRow.outerHeight(true);
1536
- this.aggregateRowHeight = $emptyAggrRow.outerHeight(true);
1534
+ $emptyAggrRow.appendDiv('table-cell table-aggregate-cell').appendSpan('text').html('&nbsp;');
1535
+ this.rowHeight = this._measureRowHeight($emptyRow);
1536
+ this.aggregateRowHeight = this._measureRowHeight($emptyAggrRow);
1537
1537
  $emptyRow.remove();
1538
1538
  $emptyAggrRow.remove();
1539
1539
  }
@@ -1546,14 +1546,14 @@ export default class Table extends Widget {
1546
1546
  if (!row.$row) {
1547
1547
  row.height = null;
1548
1548
  } else {
1549
- row.height = row.$row.outerHeight(true);
1549
+ row.height = this._measureRowHeight(row.$row);
1550
1550
  }
1551
1551
  });
1552
1552
  this._aggregateRows.forEach(aggregateRow => {
1553
1553
  if (!aggregateRow.$row) {
1554
1554
  aggregateRow.height = null;
1555
1555
  } else {
1556
- aggregateRow.height = aggregateRow.$row.outerHeight(true);
1556
+ aggregateRow.height = this._measureRowHeight(aggregateRow.$row);
1557
1557
  }
1558
1558
  });
1559
1559
  }
@@ -1867,7 +1867,7 @@ export default class Table extends Widget {
1867
1867
  }
1868
1868
 
1869
1869
  this._destroyTooltipsForRow(row);
1870
- this._removeCellEditorForRow(row);
1870
+ this._destroyCellEditorForRow(row);
1871
1871
 
1872
1872
  // Do not remove rows which are removed using an animation
1873
1873
  if (!$row.hasClass('hiding')) {
@@ -1937,7 +1937,7 @@ export default class Table extends Widget {
1937
1937
  * is expected to be linked with the corresponding '$row' (row.$row and $row.data('row')).
1938
1938
  */
1939
1939
  _installRow(row) {
1940
- row.height = row.$row.outerHeight(true);
1940
+ row.height = this._measureRowHeight(row.$row);
1941
1941
 
1942
1942
  if (row.hasError) {
1943
1943
  this._showCellErrorForRow(row);
@@ -2397,14 +2397,14 @@ export default class Table extends Widget {
2397
2397
  return;
2398
2398
  }
2399
2399
 
2400
- let $aggregateRow = this._buildAggregateRowDiv(aggregateRow);
2400
+ let $aggregateRow = this._build$AggregateRow(aggregateRow);
2401
2401
  $aggregateRow[insertFunc](refRow.$row).width(this.rowWidth);
2402
2402
 
2403
2403
  this.visibleColumns()
2404
2404
  .map(column => $(column.buildCellForAggregateRow(aggregateRow)).appendTo($aggregateRow))
2405
2405
  .forEach($c => this._resizeAggregateCell($c));
2406
2406
 
2407
- aggregateRow.height = $aggregateRow.outerHeight(true);
2407
+ aggregateRow.height = this._measureRowHeight($aggregateRow);
2408
2408
  aggregateRow.$row = $aggregateRow;
2409
2409
  if (animate) {
2410
2410
  this._showRow(aggregateRow);
@@ -2412,7 +2412,7 @@ export default class Table extends Widget {
2412
2412
  }, this);
2413
2413
  }
2414
2414
 
2415
- _buildAggregateRowDiv(aggregateRow) {
2415
+ _build$AggregateRow(aggregateRow) {
2416
2416
  let onTop = this.groupingStyle === Table.GroupingStyle.TOP;
2417
2417
  let $aggregateRow = this.$container
2418
2418
  .makeDiv('table-aggregate-row')
@@ -2983,7 +2983,7 @@ export default class Table extends Widget {
2983
2983
  oldRow.$row.replaceWith($updatedRow);
2984
2984
  Table.linkRowToDiv(row, $updatedRow);
2985
2985
  this._destroyTooltipsForRow(row);
2986
- this._removeCellEditorForRow(row);
2986
+ this._destroyCellEditorForRow(row);
2987
2987
  this._installRow(row);
2988
2988
  if (oldRow.$row.hasClass('showing') && oldRow.$row.outerHeight() < row.$row.outerHeight() / 3) {
2989
2989
  // If the row was being shown by an animation, start the animation again for the new row, otherwise row would immediately appear without animation.
@@ -3053,9 +3053,9 @@ export default class Table extends Widget {
3053
3053
  }
3054
3054
  }
3055
3055
 
3056
- _removeCellEditorForRow(row) {
3056
+ _destroyCellEditorForRow(row) {
3057
3057
  if (this.cellEditorPopup && this.cellEditorPopup.rendered && this.cellEditorPopup.row.id === row.id) {
3058
- this.cellEditorPopup.remove();
3058
+ this.cellEditorPopup.destroy();
3059
3059
  }
3060
3060
  }
3061
3061
 
@@ -4853,7 +4853,7 @@ export default class Table extends Widget {
4853
4853
  this.$data.setEnabled(enabled);
4854
4854
  }
4855
4855
 
4856
- this.$container.setTabbable(enabled);
4856
+ this.$container.setTabbableOrFocusable(enabled);
4857
4857
  }
4858
4858
 
4859
4859
  /**
@@ -4996,8 +4996,11 @@ export default class Table extends Widget {
4996
4996
  }
4997
4997
 
4998
4998
  _heightForRow(row) {
4999
- let height = 0,
4999
+ let height = 0;
5000
+ let aggregateRow = row.aggregateRowBefore;
5001
+ if (this.groupingStyle === Table.GroupingStyle.BOTTOM) {
5000
5002
  aggregateRow = row.aggregateRowAfter;
5003
+ }
5001
5004
 
5002
5005
  if (row.height) {
5003
5006
  height = row.height;
@@ -5017,6 +5020,10 @@ export default class Table extends Widget {
5017
5020
  return height;
5018
5021
  }
5019
5022
 
5023
+ _measureRowHeight($row) {
5024
+ return graphics.size($row, {includeMargin: true, exact: true}).height;
5025
+ }
5026
+
5020
5027
  /**
5021
5028
  * Returns a range of size this.viewRangeSize. Start of range is rowIndex - viewRangeSize / 4.
5022
5029
  * -> 1/4 of the rows are before the viewport 2/4 in the viewport 1/4 after the viewport,
@@ -5404,7 +5411,6 @@ export default class Table extends Widget {
5404
5411
  if (promise.state() === 'resolved') {
5405
5412
  // Do it immediately if promise has already been resolved.
5406
5413
  // This makes sure updateRow does not immediately reopen the editor after closing.
5407
- // At least for Scout JS, for Scout Classic it prevents flickering (endCellEdit comes after updateRows, but updateRows does not know whether the editor is closing so it will reopen it)
5408
5414
  destroyEditor();
5409
5415
  } else {
5410
5416
  promise.then(destroyEditor);
@@ -5443,7 +5449,7 @@ export default class Table extends Widget {
5443
5449
  // same as on Tree.prototype._onDesktopPopupOpen
5444
5450
  _onDesktopPopupOpen(event) {
5445
5451
  let popup = event.popup;
5446
- if (!this.enabledComputed) {
5452
+ if (!this.isFocusable(false)) {
5447
5453
  return;
5448
5454
  }
5449
5455
  // Set table style to focused if a context menu or a menu bar popup opens, so that it looks as it still has the focus
@@ -442,6 +442,9 @@
442
442
  .table-cell-icon {
443
443
  .font-icon& {
444
444
  color: @icon-color;
445
+ font-size: @table-cell-font-icon-size;
446
+ line-height: @table-cell-font-icon-line-height;
447
+ vertical-align: top;
445
448
 
446
449
  .disabled & {
447
450
  color: @disabled-color;
@@ -466,15 +469,12 @@
466
469
  overflow: hidden;
467
470
  padding-left: var(--table-row-margin-x);
468
471
  padding-right: var(--table-row-margin-x);
472
+ font-size: @table-aggregate-row-font-size;
469
473
 
470
474
  & > .table-cell {
471
475
  padding: var(--table-row-padding-y) @table-cell-padding-right 0 @table-cell-padding-left;
472
476
  border-bottom: 0;
473
477
  height: 100%;
474
-
475
- & > .font-icon {
476
- margin-top: 1px;
477
- }
478
478
  }
479
479
  }
480
480
 
@@ -486,7 +486,7 @@
486
486
  margin-top: -1px; // top border should cover bottom border of the previous row
487
487
  padding-left: var(--table-row-margin-x);
488
488
  padding-right: var(--table-row-margin-x);
489
- font-size: 12px;
489
+ font-size: @table-aggregate-row-font-size;
490
490
 
491
491
  & > .table-cell {
492
492
  border-bottom: 0;
@@ -518,10 +518,17 @@
518
518
  display: inline-block;
519
519
  color: @text-color;
520
520
  vertical-align: middle;
521
+ line-height: @table-aggregate-cell-font-icon-line-height;
522
+ }
523
+
524
+ &.sum > .table-cell-icon,
525
+ &.avg > .table-cell-icon {
526
+ font-size: @table-aggregate-sum-avg-font-icon-size;
521
527
  }
522
528
 
523
- &.sum > .table-cell-icon, &.avg > .table-cell-icon {
524
- font-size: @font-size-extra-small;
529
+ &.min > .table-cell-icon,
530
+ &.max > .table-cell-icon {
531
+ font-size: @table-aggregate-min-max-font-icon-size;
525
532
  }
526
533
 
527
534
  /* if aggregation is based on selected rows */
@@ -187,26 +187,20 @@ export default class TableAdapter extends ModelAdapter {
187
187
 
188
188
  _onWidgetCompleteCellEdit(event) {
189
189
  event.preventDefault();
190
- this._sendCompleteCellEdit(event.field);
190
+ this._sendCompleteCellEdit();
191
191
  }
192
192
 
193
- _sendCompleteCellEdit(field) {
194
- let data = {
195
- fieldId: field.id
196
- };
197
- this._send('completeCellEdit', data);
193
+ _sendCompleteCellEdit() {
194
+ this._send('completeCellEdit');
198
195
  }
199
196
 
200
197
  _onWidgetCancelCellEdit(event) {
201
198
  event.preventDefault();
202
- this._sendCancelCellEdit(event.field);
199
+ this._sendCancelCellEdit();
203
200
  }
204
201
 
205
- _sendCancelCellEdit(field) {
206
- let data = {
207
- fieldId: field.id
208
- };
209
- this._send('cancelCellEdit', data);
202
+ _sendCancelCellEdit() {
203
+ this._send('cancelCellEdit');
210
204
  }
211
205
 
212
206
  _onWidgetRowsChecked(event) {
@@ -507,6 +501,9 @@ export default class TableAdapter extends ModelAdapter {
507
501
 
508
502
  _onEndCellEdit(fieldId) {
509
503
  let field = this.session.getModelAdapter(fieldId);
504
+ if (!field) {
505
+ throw new Error('Field adapter could not be resolved. Id: ' + fieldId);
506
+ }
510
507
  this.widget.endCellEdit(field.widget);
511
508
  }
512
509
 
@@ -8,7 +8,7 @@
8
8
  * Contributors:
9
9
  * BSI Business Systems Integration AG - initial API and implementation
10
10
  */
11
- import {Action, TableHeaderMenuButtonKeyStroke} from '../index';
11
+ import {Action, ActionExecKeyStroke} from '../index';
12
12
 
13
13
  export default class TableHeaderMenuButton extends Action {
14
14
 
@@ -24,7 +24,7 @@ export default class TableHeaderMenuButton extends Action {
24
24
  _initKeyStrokeContext() {
25
25
  super._initKeyStrokeContext();
26
26
 
27
- this.keyStrokeContext.registerKeyStroke([new TableHeaderMenuButtonKeyStroke(this)]);
27
+ this.keyStrokeContext.registerKeyStroke([new ActionExecKeyStroke(this)]);
28
28
  }
29
29
 
30
30
  _render() {
@@ -104,6 +104,12 @@ export default class TableLayout extends AbstractLayout {
104
104
  // Always render viewport (not only when viewRangeSize changes), because view range depends on scroll position and data height
105
105
  this.table._renderViewport();
106
106
 
107
+ // Render scroll top again to make sure the data is really at the correct position after rendering viewport.
108
+ // Somehow table.$data[0].scrollTop changes during _renderViewport sometimes (e.g. when there are aggregate rows)
109
+ if (!htmlContainer.layouted) {
110
+ this.table._renderScrollTop();
111
+ }
112
+
107
113
  // Make sure tooltips and editor popup are at correct position after layouting (e.g after window resizing)
108
114
  this.table.tooltips.forEach(tooltip => {
109
115
  if (tooltip.rendered) {
@@ -71,7 +71,7 @@ export default class Column {
71
71
 
72
72
  static DEFAULT_MIN_WIDTH = 60;
73
73
  static SMALL_MIN_WIDTH = 38;
74
- static NARROW_MIN_WIDTH = 32;
74
+ static NARROW_MIN_WIDTH = 34;
75
75
 
76
76
  init(model) {
77
77
  this.session = model.session;
@@ -394,16 +394,19 @@ export default class Column {
394
394
  cell.field = field;
395
395
  // Override field alignment with the cell's alignment
396
396
  cell.field.gridData.horizontalAlignment = cell.horizontalAlignment;
397
+ popup = this._createEditorPopup(row, cell);
398
+ popup.$anchor = $cell;
399
+ popup.open(this.table.$data);
400
+ return popup;
401
+ }
397
402
 
398
- popup = scout.create('CellEditorPopup', {
403
+ _createEditorPopup(row, cell) {
404
+ return scout.create('CellEditorPopup', {
399
405
  parent: this.table,
400
406
  column: this,
401
407
  row: row,
402
408
  cell: cell
403
409
  });
404
- popup.$anchor = $cell;
405
- popup.open(this.table.$data);
406
- return popup;
407
410
  }
408
411
 
409
412
  /**