@eclipse-scout/core 11.0.32 → 11.0.41
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.
- package/dist/eclipse-scout-core-f05c37a693e6abaa57dc.min.js +2 -0
- package/dist/eclipse-scout-core-f05c37a693e6abaa57dc.min.js.map +1 -0
- package/dist/eclipse-scout-core-theme.css.map +1 -1
- package/dist/eclipse-scout-core.js +2205 -1759
- package/dist/eclipse-scout-core.js.map +1 -1
- package/dist/file-list +2 -2
- package/dist/texts.json +8 -0
- package/package.json +2 -2
- package/src/encoder/PlainTextEncoder.js +4 -0
- package/src/form/fields/smartfield/ProposalField.js +0 -7
- package/src/form/fields/smartfield/SmartField.js +16 -0
- package/src/form/fields/stringfield/StringField.js +11 -89
- package/src/form/fields/tagfield/TagField.js +13 -1
- package/src/index.js +2 -0
- package/src/lookup/RestLookupCall.js +51 -11
- package/src/popup/Popup.js +35 -0
- package/src/session/Session.js +7 -0
- package/src/table/Table.js +6 -3
- package/src/table/TableHeader.js +2 -1
- package/src/util/MaxLengthHandler.js +119 -0
- package/src/util/ViewportScroller.js +156 -0
- package/src/util/arrays.js +4 -7
- package/src/util/events.js +1 -1
- package/src/util/fonts.js +1 -1
- package/src/util/strings.js +9 -3
- package/dist/eclipse-scout-core-466592e50380384291c7.min.js +0 -2
- package/dist/eclipse-scout-core-466592e50380384291c7.min.js.map +0 -1
package/dist/file-list
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
eclipse-scout-core-
|
|
2
|
-
eclipse-scout-core-
|
|
1
|
+
eclipse-scout-core-f05c37a693e6abaa57dc.min.js
|
|
2
|
+
eclipse-scout-core-f05c37a693e6abaa57dc.min.js.map
|
|
3
3
|
eclipse-scout-core-theme-d1dee22d4f9b9233a432.min.css
|
|
4
4
|
eclipse-scout-core-theme-dark-7ead007f849a9c1a6ec1.min.css
|
|
5
5
|
eclipse-scout-core-theme-dark.css
|
package/dist/texts.json
CHANGED
|
@@ -127,6 +127,8 @@
|
|
|
127
127
|
"ui.PleaseWait_": "Please wait",
|
|
128
128
|
"ui.PopupBlockerDetected": "Opening a new window automatically was blocked by the browser.",
|
|
129
129
|
"ui.Reconnecting_": "Reconnecting...",
|
|
130
|
+
"ui.RejectedUpload": "Rejected File Upload",
|
|
131
|
+
"ui.RejectedUploadMsg": "The uploaded file was rejected by the security policy.",
|
|
130
132
|
"ui.Reload": "Reload",
|
|
131
133
|
"ui.ReloadData": "Reload data",
|
|
132
134
|
"ui.RemoveFilter": "Remove filter",
|
|
@@ -298,6 +300,8 @@
|
|
|
298
300
|
"ui.PleaseWait_": "Veuillez attendre",
|
|
299
301
|
"ui.PopupBlockerDetected": "L'ouverture d'une nouvelle fenêtre a été empêchée par la navigateur.",
|
|
300
302
|
"ui.Reconnecting_": "Connexion …",
|
|
303
|
+
"ui.RejectedUpload": "Téléchargement de fichier rejeté",
|
|
304
|
+
"ui.RejectedUploadMsg": "Le fichier téléchargé a été rejeté par la politique de sécurité.",
|
|
301
305
|
"ui.Reload": "Charger à nouveau",
|
|
302
306
|
"ui.ReloadData": "Nouveau chargement des données",
|
|
303
307
|
"ui.RemoveFilter": "Supprimer le filtre",
|
|
@@ -469,6 +473,8 @@
|
|
|
469
473
|
"ui.PleaseWait_": "Attendere prego",
|
|
470
474
|
"ui.PopupBlockerDetected": "Apertura automatica di una nuova finestra impedita dal browser.",
|
|
471
475
|
"ui.Reconnecting_": "Collegamento...",
|
|
476
|
+
"ui.RejectedUpload": "Caricamento file rifiutato",
|
|
477
|
+
"ui.RejectedUploadMsg": "Il file caricato è stato rifiutato dalla politica di sicurezza.",
|
|
472
478
|
"ui.Reload": "Ricarica",
|
|
473
479
|
"ui.ReloadData": "Ricarica dati",
|
|
474
480
|
"ui.RemoveFilter": "Rimuovere filtro",
|
|
@@ -645,6 +651,8 @@
|
|
|
645
651
|
"ui.PleaseWait_": "Bitte warten",
|
|
646
652
|
"ui.PopupBlockerDetected": "Das automatische Öffnen eines neuen Fensters wurde durch den Browser verhindert.",
|
|
647
653
|
"ui.Reconnecting_": "Verbinde...",
|
|
654
|
+
"ui.RejectedUpload": "Abgelehnte Datei",
|
|
655
|
+
"ui.RejectedUploadMsg": "Die hochgeladene Datei wurde durch die Sicherheitsrichtlinie abgelehnt.",
|
|
648
656
|
"ui.Reload": "Neu laden",
|
|
649
657
|
"ui.ReloadData": "Daten neu laden",
|
|
650
658
|
"ui.RemoveFilter": "Filter entfernen",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eclipse-scout/core",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.41",
|
|
4
4
|
"description": "Eclipse Scout runtime",
|
|
5
5
|
"author": "BSI Business Systems Integration AG",
|
|
6
6
|
"homepage": "https://www.eclipse.org/scout",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"release-postdependency": "releng-scripts release-publish-dependency"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@eclipse-scout/cli": "11.0.
|
|
43
|
+
"@eclipse-scout/cli": "11.0.41",
|
|
44
44
|
"@eclipse-scout/releng": "^10.0.0",
|
|
45
45
|
"jasmine-core": "3.6.0",
|
|
46
46
|
"jasmine-ajax": "4.0.0",
|
|
@@ -36,6 +36,10 @@ export default class PlainTextEncoder {
|
|
|
36
36
|
// Separate td with ' '
|
|
37
37
|
text = text.replace(/<\/td>/gi, ' ');
|
|
38
38
|
|
|
39
|
+
if (options.removeFontIcons) {
|
|
40
|
+
text = text.replace(/<span\s+class="[^"]*font-icon[^"]*">[^<]*<\/span>/gmi, '');
|
|
41
|
+
}
|
|
42
|
+
|
|
39
43
|
// Replace remaining tags
|
|
40
44
|
text = text.replace(/<[^>]+>/gi, '');
|
|
41
45
|
|
|
@@ -80,9 +80,6 @@ export default class ProposalField extends SmartField {
|
|
|
80
80
|
if (this.trimText) {
|
|
81
81
|
validValue = validValue.trim();
|
|
82
82
|
}
|
|
83
|
-
if (validValue.length > this.maxLength) {
|
|
84
|
-
validValue = validValue.substring(0, this.maxLength);
|
|
85
|
-
}
|
|
86
83
|
if (validValue === '') {
|
|
87
84
|
validValue = null;
|
|
88
85
|
}
|
|
@@ -207,10 +204,6 @@ export default class ProposalField extends SmartField {
|
|
|
207
204
|
this.setProperty('trimText', trimText);
|
|
208
205
|
}
|
|
209
206
|
|
|
210
|
-
setMaxLength(maxLength) {
|
|
211
|
-
this.setProperty('maxLength', maxLength);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
207
|
/**
|
|
215
208
|
* @override ValueField.js
|
|
216
209
|
*/
|
|
@@ -63,6 +63,8 @@ export default class SmartField extends ValueField {
|
|
|
63
63
|
// only when the result is up-to-date, we can use the selected lookup row
|
|
64
64
|
this.initActiveFilter = null;
|
|
65
65
|
this.disabledCopyOverlay = true;
|
|
66
|
+
this.maxLength = 500;
|
|
67
|
+
this.maxLengthHandler = scout.create('MaxLengthHandler', {target: this});
|
|
66
68
|
|
|
67
69
|
this._addCloneProperties(['lookupRow', 'codeType', 'lookupCall', 'activeFilter', 'activeFilterEnabled', 'activeFilterLabels',
|
|
68
70
|
'browseHierarchy', 'browseMaxRowCount', 'browseAutoExpandAll', 'browseLoadIncremental', 'searchRequired', 'columnDescriptors',
|
|
@@ -150,6 +152,7 @@ export default class SmartField extends ValueField {
|
|
|
150
152
|
.on('input', this._onFieldInput.bind(this));
|
|
151
153
|
}
|
|
152
154
|
this.addField($field);
|
|
155
|
+
this.maxLengthHandler.install($field);
|
|
153
156
|
|
|
154
157
|
if (!this.embedded) {
|
|
155
158
|
this.addMandatoryIndicator();
|
|
@@ -159,6 +162,11 @@ export default class SmartField extends ValueField {
|
|
|
159
162
|
this.addStatus();
|
|
160
163
|
}
|
|
161
164
|
|
|
165
|
+
_renderProperties() {
|
|
166
|
+
super._renderProperties();
|
|
167
|
+
this._renderMaxLength();
|
|
168
|
+
}
|
|
169
|
+
|
|
162
170
|
_renderGridData() {
|
|
163
171
|
super._renderGridData();
|
|
164
172
|
this.updateInnerAlignment({
|
|
@@ -588,6 +596,14 @@ export default class SmartField extends ValueField {
|
|
|
588
596
|
this.$field.setTabbable(this.enabledComputed);
|
|
589
597
|
}
|
|
590
598
|
|
|
599
|
+
setMaxLength(maxLength) {
|
|
600
|
+
this.setProperty('maxLength', maxLength);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
_renderMaxLength() {
|
|
604
|
+
this.maxLengthHandler.render();
|
|
605
|
+
}
|
|
606
|
+
|
|
591
607
|
setLookupCall(lookupCall) {
|
|
592
608
|
this.setProperty('lookupCall', lookupCall);
|
|
593
609
|
}
|
|
@@ -8,20 +8,7 @@
|
|
|
8
8
|
* Contributors:
|
|
9
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
10
|
*/
|
|
11
|
-
import {
|
|
12
|
-
arrays,
|
|
13
|
-
BasicField,
|
|
14
|
-
fields,
|
|
15
|
-
InputFieldKeyStrokeContext,
|
|
16
|
-
objects,
|
|
17
|
-
scout,
|
|
18
|
-
Status,
|
|
19
|
-
StringFieldCtrlEnterKeyStroke,
|
|
20
|
-
StringFieldEnterKeyStroke,
|
|
21
|
-
StringFieldLayout,
|
|
22
|
-
strings,
|
|
23
|
-
texts
|
|
24
|
-
} from '../../../index';
|
|
11
|
+
import {BasicField, fields, InputFieldKeyStrokeContext, objects, scout, Status, StringFieldCtrlEnterKeyStroke, StringFieldEnterKeyStroke, StringFieldLayout, strings, texts} from '../../../index';
|
|
25
12
|
|
|
26
13
|
export default class StringField extends BasicField {
|
|
27
14
|
constructor() {
|
|
@@ -32,6 +19,7 @@ export default class StringField extends BasicField {
|
|
|
32
19
|
this.inputMasked = false;
|
|
33
20
|
this.inputObfuscated = false;
|
|
34
21
|
this.maxLength = 4000;
|
|
22
|
+
this.maxLengthHandler = scout.create('MaxLengthHandler', {target: this});
|
|
35
23
|
this.multilineText = false;
|
|
36
24
|
this.selectionStart = 0;
|
|
37
25
|
this.selectionEnd = 0;
|
|
@@ -90,9 +78,9 @@ export default class StringField extends BasicField {
|
|
|
90
78
|
} else {
|
|
91
79
|
$field = fields.makeTextField(this.$parent);
|
|
92
80
|
}
|
|
93
|
-
$field.on('paste', this._onFieldPaste.bind(this));
|
|
94
81
|
|
|
95
82
|
this.addField($field);
|
|
83
|
+
this.maxLengthHandler.install($field);
|
|
96
84
|
this.addStatus();
|
|
97
85
|
}
|
|
98
86
|
|
|
@@ -185,35 +173,6 @@ export default class StringField extends BasicField {
|
|
|
185
173
|
return super.isClearable() && !this.multilineText;
|
|
186
174
|
}
|
|
187
175
|
|
|
188
|
-
setMaxLength(maxLength) {
|
|
189
|
-
this.setProperty('maxLength', maxLength);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
_renderMaxLength() {
|
|
193
|
-
// Check if "maxLength" attribute is supported by browser
|
|
194
|
-
if (this.$field[0].maxLength) {
|
|
195
|
-
this.$field.attr('maxlength', this.maxLength);
|
|
196
|
-
} else {
|
|
197
|
-
// Fallback for IE9
|
|
198
|
-
this.$field.on('keyup paste', e => {
|
|
199
|
-
setTimeout(truncate.bind(this), 0);
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Make sure current text does not exceed max length
|
|
204
|
-
truncate.call(this);
|
|
205
|
-
if (!this.rendering) {
|
|
206
|
-
this.parseAndSetValue(this._readDisplayText());
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function truncate() {
|
|
210
|
-
let text = this.$field.val();
|
|
211
|
-
if (text.length > this.maxLength) {
|
|
212
|
-
this.$field.val(text.slice(0, this.maxLength));
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
176
|
setSelectionStart(selectionStart) {
|
|
218
177
|
this.setProperty('selectionStart', selectionStart);
|
|
219
178
|
}
|
|
@@ -432,6 +391,14 @@ export default class StringField extends BasicField {
|
|
|
432
391
|
});
|
|
433
392
|
}
|
|
434
393
|
|
|
394
|
+
setMaxLength(maxLength) {
|
|
395
|
+
this.setProperty('maxLength', maxLength);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
_renderMaxLength() {
|
|
399
|
+
this.maxLengthHandler.render();
|
|
400
|
+
}
|
|
401
|
+
|
|
435
402
|
_onIconClick(event) {
|
|
436
403
|
this.acceptInput();
|
|
437
404
|
this.$field.focus();
|
|
@@ -561,51 +528,6 @@ export default class StringField extends BasicField {
|
|
|
561
528
|
}
|
|
562
529
|
}
|
|
563
530
|
|
|
564
|
-
/**
|
|
565
|
-
* Get clipboard data, different strategies for browsers.
|
|
566
|
-
* Must use a callback because this is required by Chrome's clipboard API.
|
|
567
|
-
*/
|
|
568
|
-
_getClipboardData(event, doneHandler) {
|
|
569
|
-
let data = event.originalEvent.clipboardData || this.$container.window(true).clipboardData;
|
|
570
|
-
if (data) {
|
|
571
|
-
// Chrome, Firefox
|
|
572
|
-
if (data.items && data.items.length) {
|
|
573
|
-
let item = arrays.find(data.items, item => {
|
|
574
|
-
return item.type === 'text/plain';
|
|
575
|
-
});
|
|
576
|
-
if (item) {
|
|
577
|
-
item.getAsString(doneHandler);
|
|
578
|
-
}
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
// IE, Safari
|
|
583
|
-
if (data.getData) {
|
|
584
|
-
doneHandler(data.getData('Text'));
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
// Can't access clipboard -> don't call done handler
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
_onFieldPaste(event) {
|
|
592
|
-
// must store text and selection because when the callback is executed, the clipboard content has already been applied to the input field
|
|
593
|
-
let text = this.$field.val();
|
|
594
|
-
let selection = this._getSelection();
|
|
595
|
-
|
|
596
|
-
this._getClipboardData(event, pastedText => {
|
|
597
|
-
if (!pastedText) {
|
|
598
|
-
return;
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
// Make sure the user is notified about pasted text which is cut off because of maxlength constraints
|
|
602
|
-
text = this._applyTextToSelection(text, pastedText, selection);
|
|
603
|
-
if (text.length > this.maxLength) {
|
|
604
|
-
this._showNotification('ui.PastedTextTooLong');
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
|
|
609
531
|
_showNotification(textKey) {
|
|
610
532
|
scout.create('DesktopNotification', {
|
|
611
533
|
parent: this,
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import {
|
|
12
12
|
arrays,
|
|
13
|
+
fields,
|
|
13
14
|
HtmlComponent,
|
|
14
15
|
InputFieldKeyStrokeContext,
|
|
15
|
-
fields,
|
|
16
16
|
keys,
|
|
17
17
|
LookupCall,
|
|
18
18
|
scout,
|
|
@@ -38,6 +38,8 @@ export default class TagField extends ValueField {
|
|
|
38
38
|
this.lookupCall = null;
|
|
39
39
|
this._currentLookupCall = null;
|
|
40
40
|
this.tagBar = null;
|
|
41
|
+
this.maxLength = 500;
|
|
42
|
+
this.maxLengthHandler = scout.create('MaxLengthHandler', {target: this});
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
_init(model) {
|
|
@@ -85,12 +87,14 @@ export default class TagField extends ValueField {
|
|
|
85
87
|
.on('input', this._onFieldInput.bind(this));
|
|
86
88
|
this.addFieldContainer($fieldContainer);
|
|
87
89
|
this.addField($field);
|
|
90
|
+
this.maxLengthHandler.install($field);
|
|
88
91
|
this.addStatus();
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
_renderProperties() {
|
|
92
95
|
super._renderProperties();
|
|
93
96
|
this._renderValue();
|
|
97
|
+
this._renderMaxLength();
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
_renderValue() {
|
|
@@ -155,6 +159,14 @@ export default class TagField extends ValueField {
|
|
|
155
159
|
}
|
|
156
160
|
}
|
|
157
161
|
|
|
162
|
+
setMaxLength(maxLength) {
|
|
163
|
+
this.setProperty('maxLength', maxLength);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
_renderMaxLength() {
|
|
167
|
+
this.maxLengthHandler.render();
|
|
168
|
+
}
|
|
169
|
+
|
|
158
170
|
_updateInputVisible() {
|
|
159
171
|
let visible, oldVisible = !this.$field.isVisible();
|
|
160
172
|
if (this.enabledComputed) {
|
package/src/index.js
CHANGED
|
@@ -42,6 +42,7 @@ export {default as fonts} from './util/fonts';
|
|
|
42
42
|
export {default as icons} from './util/icons';
|
|
43
43
|
export {default as inspector} from './util/inspector';
|
|
44
44
|
export {default as locales} from './util/locales';
|
|
45
|
+
export {default as MaxLengthHandler} from './util/MaxLengthHandler';
|
|
45
46
|
export {default as logging} from './logging/logging';
|
|
46
47
|
export {default as NullLogger} from './logging/NullLogger';
|
|
47
48
|
export {default as mimeTypes} from './util/mimeTypes';
|
|
@@ -69,6 +70,7 @@ export {default as HAlign} from './util/HAlign';
|
|
|
69
70
|
export {default as aggregation} from './util/aggregation';
|
|
70
71
|
export {default as webstorage} from './util/webstorage';
|
|
71
72
|
export {default as cookies} from './util/cookies';
|
|
73
|
+
export {default as ViewportScroller} from './util/ViewportScroller';
|
|
72
74
|
export {default as ajax} from './ajax/ajax';
|
|
73
75
|
export {default as AjaxCall} from './ajax/AjaxCall';
|
|
74
76
|
export {default as AjaxError} from './ajax/AjaxError';
|
|
@@ -8,9 +8,38 @@
|
|
|
8
8
|
* Contributors:
|
|
9
9
|
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
10
|
*/
|
|
11
|
-
import {arrays, LookupCall, scout} from '../index';
|
|
11
|
+
import {arrays, LookupCall, objects, scout} from '../index';
|
|
12
12
|
import $ from 'jquery';
|
|
13
13
|
|
|
14
|
+
/**
|
|
15
|
+
* A lookup call that can load lookup rows from a REST service.
|
|
16
|
+
*
|
|
17
|
+
* API:
|
|
18
|
+
* ----
|
|
19
|
+
* By default, the REST service is expected to listen for POST requests at the URL defined by
|
|
20
|
+
* this.resourceUrl. It receives a restriction object and must return a list of matching lookup rows.
|
|
21
|
+
* The serialization format is JSON.
|
|
22
|
+
*
|
|
23
|
+
* Lookup rows:
|
|
24
|
+
* ------------
|
|
25
|
+
* The standard lookup row properties defined by Scout are usually sufficient (see AbstractLookupRowDo.java).
|
|
26
|
+
*
|
|
27
|
+
* Restriction:
|
|
28
|
+
* ------------
|
|
29
|
+
* The restriction object consists of a number of 'well-known' properties (e.g. 'text' in QueryBy.TEXT
|
|
30
|
+
* mode, see AbstractLookupRestrictionDo.java for details) and additional, service-dependent properties
|
|
31
|
+
* that can either be predefined in the model or added programmatically at runtime. Since all of those
|
|
32
|
+
* properties are sent in the same restriction object, some care must be taken to prevent accidental
|
|
33
|
+
* overwriting of properties.
|
|
34
|
+
*
|
|
35
|
+
* Order of precedence (lowest to highest):
|
|
36
|
+
* 1. Restrictions automatically applied to all clones after their creation in the respective cloneFor method.
|
|
37
|
+
* These are: 'active' (ALL, TEXT, REC) and 'maxRowCount' (ALL, TEXT, REC)
|
|
38
|
+
* 2. Restrictions predefined in the model property 'restriction', shared by all clones.
|
|
39
|
+
* 3. Restrictions applied to clones programmatically, e.g. during a 'prepareLookupCall' event.
|
|
40
|
+
* 4. Hard-coded properties that are fundamental to the respective queryBy mode (cannot be overridden).
|
|
41
|
+
* These are: 'ids' (KEY, KEYS) and 'text' (TEXT)
|
|
42
|
+
*/
|
|
14
43
|
export default class RestLookupCall extends LookupCall {
|
|
15
44
|
|
|
16
45
|
constructor() {
|
|
@@ -42,6 +71,17 @@ export default class RestLookupCall extends LookupCall {
|
|
|
42
71
|
this._restriction[key] = value;
|
|
43
72
|
}
|
|
44
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Adds the given key-value pair to 'this._restriction', but only if there is no predefined
|
|
76
|
+
* value for this key in 'this.restriction'. This prevents unintentional overriding of
|
|
77
|
+
* user-defined model restrictions.
|
|
78
|
+
*/
|
|
79
|
+
_addRestrictionIfAbsent(key, value) {
|
|
80
|
+
if (!this.restriction || objects.isNullOrUndefined(this.restriction[key])) {
|
|
81
|
+
this.addRestriction(key, value);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
45
85
|
_getAll() {
|
|
46
86
|
return this._call();
|
|
47
87
|
}
|
|
@@ -63,22 +103,22 @@ export default class RestLookupCall extends LookupCall {
|
|
|
63
103
|
|
|
64
104
|
cloneForAll() {
|
|
65
105
|
let clone = super.cloneForAll();
|
|
66
|
-
clone.
|
|
67
|
-
clone.
|
|
106
|
+
clone._addRestrictionIfAbsent('active', true);
|
|
107
|
+
clone._addRestrictionIfAbsent('maxRowCount', this.maxRowCount);
|
|
68
108
|
return clone;
|
|
69
109
|
}
|
|
70
110
|
|
|
71
111
|
cloneForText(text) {
|
|
72
112
|
let clone = super.cloneForText(text);
|
|
73
|
-
clone.
|
|
74
|
-
clone.
|
|
113
|
+
clone._addRestrictionIfAbsent('active', true);
|
|
114
|
+
clone._addRestrictionIfAbsent('maxRowCount', this.maxRowCount);
|
|
75
115
|
return clone;
|
|
76
116
|
}
|
|
77
117
|
|
|
78
118
|
cloneForRec(parentKey) {
|
|
79
119
|
let clone = super.cloneForRec(parentKey);
|
|
80
|
-
clone.
|
|
81
|
-
clone.
|
|
120
|
+
clone._addRestrictionIfAbsent('active', true);
|
|
121
|
+
clone._addRestrictionIfAbsent('maxRowCount', this.maxRowCount);
|
|
82
122
|
return clone;
|
|
83
123
|
}
|
|
84
124
|
|
|
@@ -167,7 +207,7 @@ export default class RestLookupCall extends LookupCall {
|
|
|
167
207
|
return value;
|
|
168
208
|
};
|
|
169
209
|
|
|
170
|
-
let
|
|
210
|
+
let resolvedRestriction = {};
|
|
171
211
|
let restriction = $.extend({}, this.restriction, this._restriction);
|
|
172
212
|
Object.keys(restriction).forEach(key => {
|
|
173
213
|
let value = restriction[key];
|
|
@@ -180,11 +220,11 @@ export default class RestLookupCall extends LookupCall {
|
|
|
180
220
|
newValue = resolveValue(value);
|
|
181
221
|
}
|
|
182
222
|
// Only add non-null restrictions
|
|
183
|
-
if (newValue) {
|
|
184
|
-
|
|
223
|
+
if (!objects.isNullOrUndefined(newValue)) {
|
|
224
|
+
resolvedRestriction[key] = newValue;
|
|
185
225
|
}
|
|
186
226
|
});
|
|
187
|
-
return
|
|
227
|
+
return resolvedRestriction;
|
|
188
228
|
}
|
|
189
229
|
|
|
190
230
|
_createAjaxCall() {
|
package/src/popup/Popup.js
CHANGED
|
@@ -104,14 +104,49 @@ export default class Popup extends Widget {
|
|
|
104
104
|
|
|
105
105
|
// Note that these strings are also used as CSS classes
|
|
106
106
|
static Alignment = {
|
|
107
|
+
/**
|
|
108
|
+
* The entire popup is positioned horizontally left of the anchor.
|
|
109
|
+
*/
|
|
107
110
|
LEFT: 'left',
|
|
111
|
+
/**
|
|
112
|
+
* With arrow: The arrow at the left edge of the popup is aligned horizontally with the center of the anchor.
|
|
113
|
+
* <p>
|
|
114
|
+
* Without arrow: The left edges of both the popup and the anchor are aligned horizontally.
|
|
115
|
+
*/
|
|
108
116
|
LEFTEDGE: 'leftedge',
|
|
117
|
+
/**
|
|
118
|
+
* The entire popup is positioned vertically above the anchor.
|
|
119
|
+
*/
|
|
109
120
|
TOP: 'top',
|
|
121
|
+
/**
|
|
122
|
+
* With arrow: The arrow at the top edge of the popup is aligned vertically with the center of the anchor.
|
|
123
|
+
* <p>
|
|
124
|
+
* Without arrow: The top edges of both the popup and the anchor are aligned vertically.
|
|
125
|
+
*/
|
|
110
126
|
TOPEDGE: 'topedge',
|
|
127
|
+
/**
|
|
128
|
+
* The centers of both the popup and the anchor are aligned in the respective dimension.
|
|
129
|
+
*/
|
|
111
130
|
CENTER: 'center',
|
|
131
|
+
/**
|
|
132
|
+
* The entire popup is positioned horizontally to the right of the anchor.
|
|
133
|
+
*/
|
|
112
134
|
RIGHT: 'right',
|
|
135
|
+
/**
|
|
136
|
+
* With arrow: The arrow at the right edge of the popup is aligned horizontally with the center of the anchor.
|
|
137
|
+
* <p>
|
|
138
|
+
* Without arrow: The right edges of both the popup and the anchor are aligned horizontally.
|
|
139
|
+
*/
|
|
113
140
|
RIGHTEDGE: 'rightedge',
|
|
141
|
+
/**
|
|
142
|
+
* The entire popup is positioned vertically below the anchor.
|
|
143
|
+
*/
|
|
114
144
|
BOTTOM: 'bottom',
|
|
145
|
+
/**
|
|
146
|
+
* With arrow: The arrow at the bottom edge of the popup is aligned vertically with the center of the anchor.
|
|
147
|
+
* <p>
|
|
148
|
+
* Without arrow: The bottom edges of both the popup and the anchor are aligned vertically.
|
|
149
|
+
*/
|
|
115
150
|
BOTTOMEDGE: 'bottomedge'
|
|
116
151
|
};
|
|
117
152
|
|
package/src/session/Session.js
CHANGED
|
@@ -122,6 +122,7 @@ export default class Session {
|
|
|
122
122
|
SESSION_TIMEOUT: 10,
|
|
123
123
|
UI_PROCESSING: 20,
|
|
124
124
|
UNSAFE_UPLOAD: 30,
|
|
125
|
+
REJECTED_UPLOAD: 31,
|
|
125
126
|
VERSION_MISMATCH: 40
|
|
126
127
|
};
|
|
127
128
|
|
|
@@ -1048,6 +1049,12 @@ export default class Session {
|
|
|
1048
1049
|
boxOptions.yesButtonText = this.optText('ui.Ok', 'Ok');
|
|
1049
1050
|
boxOptions.yesButtonAction = () => {
|
|
1050
1051
|
};
|
|
1052
|
+
} else if (jsonError.code === Session.JsonResponseError.REJECTED_UPLOAD) {
|
|
1053
|
+
boxOptions.header = this.optText('ui.RejectedUpload', boxOptions.header);
|
|
1054
|
+
boxOptions.body = this.optText('ui.RejectedUploadMsg', boxOptions.body);
|
|
1055
|
+
boxOptions.yesButtonText = this.optText('ui.Ok', 'Ok');
|
|
1056
|
+
boxOptions.yesButtonAction = () => {
|
|
1057
|
+
};
|
|
1051
1058
|
}
|
|
1052
1059
|
this.showFatalMessage(boxOptions, jsonError.code);
|
|
1053
1060
|
}
|
package/src/table/Table.js
CHANGED
|
@@ -864,13 +864,16 @@ export default class Table extends Widget {
|
|
|
864
864
|
|
|
865
865
|
if (tooltipText) {
|
|
866
866
|
return tooltipText;
|
|
867
|
-
}
|
|
867
|
+
}
|
|
868
|
+
if ($row.data('aggregateRow') && $cell.text().trim() && ($cell.isContentTruncated() || ($cell.children('.table-cell-icon').length && !$cell.children('.table-cell-icon').isVisible()))) {
|
|
868
869
|
$cell = $cell.clone();
|
|
869
870
|
$cell.children('.table-cell-icon').setVisible(true);
|
|
870
871
|
return $cell.html();
|
|
871
|
-
}
|
|
872
|
+
}
|
|
873
|
+
if (this._isTruncatedCellTooltipEnabled(column) && $cell.isContentTruncated()) {
|
|
872
874
|
return strings.plainText($cell.html(), {
|
|
873
|
-
trim: true
|
|
875
|
+
trim: true,
|
|
876
|
+
removeFontIcons: true
|
|
874
877
|
});
|
|
875
878
|
}
|
|
876
879
|
}
|
package/src/table/TableHeader.js
CHANGED
|
@@ -294,7 +294,8 @@ export default class TableHeader extends Widget {
|
|
|
294
294
|
$col = $col.clone();
|
|
295
295
|
$col.children('.table-header-item-state').remove();
|
|
296
296
|
let text = strings.plainText($col.html(), {
|
|
297
|
-
trim: true
|
|
297
|
+
trim: true,
|
|
298
|
+
removeFontIcons: true
|
|
298
299
|
});
|
|
299
300
|
if (strings.hasText(text)) {
|
|
300
301
|
return text;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2010-2021 BSI Business Systems Integration AG.
|
|
3
|
+
* All rights reserved. This program and the accompanying materials
|
|
4
|
+
* are made available under the terms of the Eclipse Public License v1.0
|
|
5
|
+
* which accompanies this distribution, and is available at
|
|
6
|
+
* http://www.eclipse.org/legal/epl-v10.html
|
|
7
|
+
*
|
|
8
|
+
* Contributors:
|
|
9
|
+
* BSI Business Systems Integration AG - initial API and implementation
|
|
10
|
+
*/
|
|
11
|
+
import {arrays, objects, scout, Status} from '../index';
|
|
12
|
+
import $ from 'jquery';
|
|
13
|
+
import {assertValue} from '../scout';
|
|
14
|
+
|
|
15
|
+
export default class MaxLengthHandler {
|
|
16
|
+
|
|
17
|
+
constructor(options) {
|
|
18
|
+
options = options || {};
|
|
19
|
+
assertValue(options.target, 'target is mandatory');
|
|
20
|
+
|
|
21
|
+
this.$textInputField = null;
|
|
22
|
+
this.onInputFieldPaste = this._onInputFieldPaste.bind(this);
|
|
23
|
+
$.extend(this, options);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
install($textInputField) {
|
|
27
|
+
this.uninstall();
|
|
28
|
+
if (!$textInputField || (!$textInputField.is('input:text') && !$textInputField.is('textarea'))) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
if ($textInputField) {
|
|
32
|
+
this.$textInputField = $textInputField;
|
|
33
|
+
this.$textInputField.on('paste', this.onInputFieldPaste);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
uninstall() {
|
|
38
|
+
if (this.$textInputField) {
|
|
39
|
+
this.$textInputField.off('paste', this.onInputFieldPaste);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
render() {
|
|
44
|
+
if (!this.$textInputField || objects.isNullOrUndefined(this.target.maxLength)) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.$textInputField.attr('maxlength', this.target.maxLength);
|
|
48
|
+
|
|
49
|
+
// Make sure current text does not exceed max length
|
|
50
|
+
let text = this.$textInputField.val();
|
|
51
|
+
if (text.length > this.target.maxLength) {
|
|
52
|
+
this.$textInputField.val(text.slice(0, this.target.maxLength));
|
|
53
|
+
}
|
|
54
|
+
if (!this.target.rendering) {
|
|
55
|
+
this.target.parseAndSetValue(this.target._readDisplayText());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
_onInputFieldPaste(event) {
|
|
60
|
+
if (!this.$textInputField || objects.isNullOrUndefined(this.target.maxLength)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// must read out the text and selection size now because when the callback is executed, the clipboard content has already been applied to the input field
|
|
64
|
+
let textSize = this.$textInputField.val().length - this._getSelectionSize();
|
|
65
|
+
|
|
66
|
+
this._getClipboardData(event, pastedText => {
|
|
67
|
+
if (!pastedText) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if ((textSize + pastedText.length) > this.target.maxLength) {
|
|
71
|
+
this._showNotification('ui.PastedTextTooLong');
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
_getSelectionSize() {
|
|
77
|
+
let start = scout.nvl(this.$textInputField[0].selectionStart, null);
|
|
78
|
+
let end = scout.nvl(this.$textInputField[0].selectionEnd, null);
|
|
79
|
+
if (start === null || end === null) {
|
|
80
|
+
return 0;
|
|
81
|
+
}
|
|
82
|
+
return end - start;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get clipboard data, different strategies for browsers.
|
|
87
|
+
* Must use a callback because this is required by Chrome's clipboard API.
|
|
88
|
+
*/
|
|
89
|
+
_getClipboardData(event, doneHandler) {
|
|
90
|
+
let data = event.originalEvent.clipboardData || this.target.$container.window(true).clipboardData;
|
|
91
|
+
if (data) {
|
|
92
|
+
// Chrome, Firefox
|
|
93
|
+
if (data.items && data.items.length) {
|
|
94
|
+
let item = arrays.find(data.items, item => {
|
|
95
|
+
return item.type === 'text/plain';
|
|
96
|
+
});
|
|
97
|
+
if (item) {
|
|
98
|
+
item.getAsString(doneHandler);
|
|
99
|
+
}
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// IE, Safari
|
|
104
|
+
if (data.getData) {
|
|
105
|
+
doneHandler(data.getData('Text'));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Can't access clipboard -> don't call done handler
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_showNotification(textKey) {
|
|
113
|
+
scout.create('DesktopNotification', {
|
|
114
|
+
parent: this.target,
|
|
115
|
+
severity: Status.Severity.WARNING,
|
|
116
|
+
message: this.target.session.text(textKey)
|
|
117
|
+
}).show();
|
|
118
|
+
}
|
|
119
|
+
}
|