cx 26.1.13 → 26.2.1
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/build/charts/Marker.d.ts +1 -1
- package/build/charts/Marker.d.ts.map +1 -1
- package/build/charts/Marker.js +16 -6
- package/build/charts/MouseTracker.d.ts +2 -0
- package/build/charts/MouseTracker.d.ts.map +1 -1
- package/build/charts/helpers/PointReducer.d.ts +2 -2
- package/build/charts/helpers/PointReducer.d.ts.map +1 -1
- package/build/data/View.d.ts +5 -3
- package/build/data/View.d.ts.map +1 -1
- package/build/data/View.js +3 -1
- package/build/data/ops/findTreeNode.d.ts +20 -1
- package/build/data/ops/findTreeNode.d.ts.map +1 -1
- package/build/data/ops/findTreeNode.js +19 -0
- package/build/data/ops/findTreePath.d.ts +1 -1
- package/build/data/ops/findTreePath.d.ts.map +1 -1
- package/build/data/ops/findTreePath.js +1 -1
- package/build/data/ops/removeTreeNodes.d.ts +14 -1
- package/build/data/ops/removeTreeNodes.d.ts.map +1 -1
- package/build/data/ops/removeTreeNodes.js +13 -0
- package/build/data/ops/updateArray.d.ts +1 -1
- package/build/data/ops/updateArray.d.ts.map +1 -1
- package/build/data/ops/updateArray.js +1 -1
- package/build/data/ops/updateTree.d.ts +20 -1
- package/build/data/ops/updateTree.d.ts.map +1 -1
- package/build/data/ops/updateTree.js +19 -0
- package/build/jsx-runtime.d.ts +1 -0
- package/build/jsx-runtime.d.ts.map +1 -1
- package/build/jsx-runtime.js +3 -1
- package/build/svg/Rectangle.d.ts +6 -4
- package/build/svg/Rectangle.d.ts.map +1 -1
- package/build/svg/Rectangle.js +9 -7
- package/build/ui/Instance.d.ts +1 -1
- package/build/ui/Instance.d.ts.map +1 -1
- package/build/ui/Instance.js +18 -8
- package/build/ui/IsolatedScope.d.ts +2 -1
- package/build/ui/IsolatedScope.d.ts.map +1 -1
- package/build/ui/Prop.d.ts +1 -1
- package/build/ui/Prop.d.ts.map +1 -1
- package/build/ui/Widget.d.ts +2 -0
- package/build/ui/Widget.d.ts.map +1 -1
- package/build/ui/Widget.js +4 -0
- package/build/ui/adapter/GroupAdapter.d.ts +4 -4
- package/build/ui/adapter/GroupAdapter.d.ts.map +1 -1
- package/build/ui/adapter/GroupAdapter.js +4 -4
- package/build/ui/adapter/TreeAdapter.d.ts +5 -3
- package/build/ui/adapter/TreeAdapter.d.ts.map +1 -1
- package/build/ui/adapter/TreeAdapter.js +12 -5
- package/build/ui/app/startAppLoop.d.ts +2 -2
- package/build/ui/app/startAppLoop.d.ts.map +1 -1
- package/build/ui/app/startHotAppLoop.d.ts +4 -4
- package/build/ui/app/startHotAppLoop.d.ts.map +1 -1
- package/build/ui/app/startHotAppLoop.js +1 -1
- package/build/ui/batchUpdates.d.ts.map +1 -1
- package/build/ui/batchUpdates.js +3 -4
- package/build/widgets/Button.d.ts +0 -7
- package/build/widgets/Button.d.ts.map +1 -1
- package/build/widgets/HtmlElement.d.ts +2 -2
- package/build/widgets/HtmlElement.d.ts.map +1 -1
- package/build/widgets/form/Checkbox.d.ts +3 -3
- package/build/widgets/form/Checkbox.d.ts.map +1 -1
- package/build/widgets/form/Checkbox.js +11 -6
- package/build/widgets/form/DateTimeField.d.ts +4 -0
- package/build/widgets/form/DateTimeField.d.ts.map +1 -1
- package/build/widgets/form/LookupField.d.ts +14 -27
- package/build/widgets/form/LookupField.d.ts.map +1 -1
- package/build/widgets/form/TextField.d.ts +2 -2
- package/build/widgets/form/TextField.d.ts.map +1 -1
- package/build/widgets/grid/Grid.d.ts +20 -16
- package/build/widgets/grid/Grid.d.ts.map +1 -1
- package/build/widgets/grid/Grid.js +200 -86
- package/build/widgets/nav/Menu.d.ts +2 -0
- package/build/widgets/nav/Menu.d.ts.map +1 -1
- package/build/widgets/nav/Route.js +1 -1
- package/build/widgets/overlay/FlyweightTooltipTracker.d.ts +6 -4
- package/build/widgets/overlay/FlyweightTooltipTracker.d.ts.map +1 -1
- package/build/widgets/overlay/FlyweightTooltipTracker.js +3 -0
- package/build/widgets/overlay/Overlay.d.ts +2 -2
- package/build/widgets/overlay/Overlay.d.ts.map +1 -1
- package/dist/data.js +52 -1
- package/dist/jsx-runtime.js +4 -2
- package/dist/manifest.js +879 -873
- package/dist/svg.js +3 -0
- package/dist/ui.js +1548 -1544
- package/dist/widgets.css +1 -1
- package/dist/widgets.js +395 -4
- package/package.json +2 -2
- package/src/charts/Marker.tsx +448 -394
- package/src/charts/MouseTracker.tsx +3 -0
- package/src/charts/helpers/PointReducer.ts +2 -2
- package/src/data/View.ts +76 -19
- package/src/data/ops/findTreeNode.ts +20 -1
- package/src/data/ops/findTreePath.ts +7 -2
- package/src/data/ops/removeTreeNodes.ts +14 -1
- package/src/data/ops/updateArray.ts +4 -4
- package/src/data/ops/updateTree.ts +32 -6
- package/src/index.scss +6 -6
- package/src/jsx-runtime.spec.tsx +40 -0
- package/src/jsx-runtime.ts +87 -84
- package/src/svg/Rectangle.tsx +80 -73
- package/src/ui/DataProxy.ts +55 -55
- package/src/ui/Instance.ts +142 -45
- package/src/ui/IsolatedScope.ts +4 -2
- package/src/ui/Prop.ts +141 -141
- package/src/ui/Rescope.ts +50 -50
- package/src/ui/Widget.tsx +292 -234
- package/src/ui/adapter/ArrayAdapter.ts +229 -229
- package/src/ui/adapter/GroupAdapter.ts +8 -10
- package/src/ui/adapter/TreeAdapter.ts +75 -15
- package/src/ui/app/Url.spec.ts +1 -1
- package/src/ui/app/startAppLoop.tsx +56 -45
- package/src/ui/app/startHotAppLoop.ts +4 -4
- package/src/ui/batchUpdates.ts +16 -21
- package/src/ui/exprHelpers.ts +96 -96
- package/src/widgets/Button.tsx +0 -8
- package/src/widgets/HtmlElement.spec.tsx +100 -72
- package/src/widgets/HtmlElement.tsx +11 -10
- package/src/widgets/Sandbox.ts +104 -104
- package/src/widgets/Section.scss +55 -55
- package/src/widgets/drag-drop/DropZone.scss +74 -74
- package/src/widgets/form/Checkbox.tsx +296 -243
- package/src/widgets/form/DateTimeField.tsx +6 -0
- package/src/widgets/form/LookupField.tsx +70 -73
- package/src/widgets/form/TextField.tsx +2 -2
- package/src/widgets/grid/Grid.scss +43 -10
- package/src/widgets/grid/Grid.tsx +4401 -3848
- package/src/widgets/nav/Menu.tsx +3 -0
- package/src/widgets/nav/Route.ts +1 -1
- package/src/widgets/overlay/FlyweightTooltipTracker.ts +15 -4
- package/src/widgets/overlay/Overlay.tsx +2 -1
- package/src/widgets/overlay/index.d.ts +11 -11
package/dist/ui.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
computable,
|
|
3
3
|
StoreProxy,
|
|
4
|
+
isAccessorChain,
|
|
4
5
|
StructuredSelector,
|
|
5
6
|
invalidateExpressionCache,
|
|
6
7
|
invalidateStringTemplateCache,
|
|
@@ -14,7 +15,6 @@ import {
|
|
|
14
15
|
ZoomIntoPropertyView,
|
|
15
16
|
setGetExpressionCacheCallback,
|
|
16
17
|
setGetStringTemplateCacheCallback,
|
|
17
|
-
isAccessorChain,
|
|
18
18
|
SubscribableView,
|
|
19
19
|
Store,
|
|
20
20
|
NestedDataView,
|
|
@@ -28,13 +28,21 @@ import {
|
|
|
28
28
|
isArray,
|
|
29
29
|
isFunction,
|
|
30
30
|
parseStyle,
|
|
31
|
+
SubscriberList,
|
|
32
|
+
isNonEmptyArray,
|
|
33
|
+
GlobalCacheIdentifier,
|
|
34
|
+
debug,
|
|
35
|
+
processDataFlag,
|
|
36
|
+
renderFlag,
|
|
37
|
+
destroyFlag,
|
|
38
|
+
validatedDebounce,
|
|
39
|
+
throttle,
|
|
40
|
+
isUndefined,
|
|
31
41
|
isString,
|
|
32
|
-
|
|
42
|
+
isObject,
|
|
33
43
|
isDefined,
|
|
44
|
+
Console,
|
|
34
45
|
innerTextTrim,
|
|
35
|
-
GlobalCacheIdentifier,
|
|
36
|
-
isObject,
|
|
37
|
-
SubscriberList,
|
|
38
46
|
isSelfOrDescendant,
|
|
39
47
|
getActiveElement,
|
|
40
48
|
findFirst,
|
|
@@ -46,14 +54,6 @@ import {
|
|
|
46
54
|
resolveMinMaxFractionDigits,
|
|
47
55
|
parseDateInvariant,
|
|
48
56
|
setGetFormatCacheCallback,
|
|
49
|
-
isNonEmptyArray,
|
|
50
|
-
debug,
|
|
51
|
-
processDataFlag,
|
|
52
|
-
renderFlag,
|
|
53
|
-
destroyFlag,
|
|
54
|
-
validatedDebounce,
|
|
55
|
-
throttle,
|
|
56
|
-
isUndefined,
|
|
57
57
|
TraversalStack,
|
|
58
58
|
reverseSlice,
|
|
59
59
|
appDataFlag,
|
|
@@ -262,1722 +262,1725 @@ class CSS {
|
|
|
262
262
|
CSS.classPrefix = "cx";
|
|
263
263
|
CSSHelper.alias("cx", CSS);
|
|
264
264
|
|
|
265
|
-
|
|
266
|
-
let
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
265
|
+
let isBatching = 0;
|
|
266
|
+
let promiseSubscribers = new SubscriberList();
|
|
267
|
+
function batchUpdates(callback) {
|
|
268
|
+
if (VDOM$1.DOM.unstable_batchedUpdates)
|
|
269
|
+
VDOM$1.DOM.unstable_batchedUpdates(() => {
|
|
270
|
+
isBatching++;
|
|
271
|
+
try {
|
|
272
|
+
callback();
|
|
273
|
+
} finally {
|
|
274
|
+
isBatching--;
|
|
275
|
+
}
|
|
276
|
+
});
|
|
277
|
+
else callback();
|
|
278
|
+
}
|
|
279
|
+
function isBatchingUpdates() {
|
|
280
|
+
return isBatching > 0;
|
|
281
|
+
}
|
|
282
|
+
function notifyBatchedUpdateStarting() {
|
|
283
|
+
promiseSubscribers.execute((x) => {
|
|
284
|
+
x.pending++;
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
function notifyBatchedUpdateCompleted() {
|
|
288
|
+
promiseSubscribers.execute((x) => {
|
|
289
|
+
let cb = x;
|
|
290
|
+
cb.finished++;
|
|
291
|
+
if (cb.finished >= cb.pending) cb.complete(true);
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
function batchUpdatesAndNotify(callback, notifyCallback, timeout = 1000) {
|
|
295
|
+
let done = false;
|
|
296
|
+
let timer;
|
|
297
|
+
let unsubscribe;
|
|
298
|
+
const update = {
|
|
299
|
+
pending: 0,
|
|
300
|
+
finished: 0,
|
|
301
|
+
complete: (success) => {
|
|
302
|
+
if (!done) {
|
|
303
|
+
done = true;
|
|
304
|
+
if (timer) clearInterval(timer);
|
|
305
|
+
if (unsubscribe) unsubscribe();
|
|
306
|
+
notifyCallback(!!success);
|
|
307
|
+
}
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
unsubscribe = promiseSubscribers.subscribe(update);
|
|
311
|
+
batchUpdates(callback);
|
|
312
|
+
if (update.pending <= update.finished) update.complete(true);
|
|
313
|
+
else timer = setTimeout(update.complete, timeout);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
let instanceId = 1000;
|
|
317
|
+
/**
|
|
318
|
+
* Base Instance class
|
|
319
|
+
*/
|
|
320
|
+
class Instance {
|
|
321
|
+
// Selectors
|
|
322
|
+
dataSelector;
|
|
323
|
+
// Lifecycle flags
|
|
270
324
|
initialized;
|
|
271
|
-
|
|
325
|
+
destroySubscriptions;
|
|
272
326
|
helpers;
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
this.
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
this.jsxSpread.forEach((spread) => {
|
|
283
|
-
for (const key in spread) {
|
|
284
|
-
this[key] = spread[key];
|
|
285
|
-
this.jsxAttributes.push(key);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
init() {
|
|
291
|
-
if (this.styles) this.style = this.styles;
|
|
292
|
-
if (this.styled) this.style = parseStyle(this.style);
|
|
293
|
-
if (typeof this.if !== "undefined") this.visible = this.if;
|
|
294
|
-
this.declareData();
|
|
295
|
-
if (this.outerLayout) {
|
|
296
|
-
if (isArray(this.outerLayout)) throw new Error("Only single element outer layout is supported.");
|
|
297
|
-
//TODO: better handle the case when outer layout is an array. How to get around circular dependency to PureContainer
|
|
298
|
-
this.outerLayout = Widget.create(this.outerLayout, {});
|
|
299
|
-
}
|
|
300
|
-
if (this.contentFor) this.putInto = this.contentFor;
|
|
301
|
-
if (this.putInto) this.isContent = true;
|
|
302
|
-
if (isString(this.CSS)) this.CSS = CSSHelper.get(this.CSS);
|
|
303
|
-
this.initHelpers();
|
|
304
|
-
this.initComponents();
|
|
305
|
-
this.initialized = true;
|
|
327
|
+
components;
|
|
328
|
+
constructor(widget, key, parent, parentStore) {
|
|
329
|
+
this.widget = widget;
|
|
330
|
+
this.key = key;
|
|
331
|
+
this.id = String(++instanceId);
|
|
332
|
+
this.cached = {};
|
|
333
|
+
this.parent = parent;
|
|
334
|
+
this.parentStore = parentStore ?? parent?.store;
|
|
335
|
+
if (this.parentStore == null) throw new Error("Cannot create instance without a parent store.");
|
|
306
336
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
for (const k in this.components) {
|
|
311
|
-
if (!this.components[k]) delete this.components[k];
|
|
312
|
-
}
|
|
313
|
-
}
|
|
337
|
+
setParentStore(parentStore) {
|
|
338
|
+
this.parentStore = parentStore;
|
|
339
|
+
this.widget.applyParentStore(this);
|
|
314
340
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
341
|
+
init(context) {
|
|
342
|
+
// widget is initialized when the first instance is initialized
|
|
343
|
+
if (!this.widget.initialized) {
|
|
344
|
+
this.widget.init();
|
|
345
|
+
this.widget.initialized = true;
|
|
318
346
|
}
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
if (this.styled) {
|
|
323
|
-
options.class =
|
|
324
|
-
options.className =
|
|
325
|
-
options.style =
|
|
326
|
-
{
|
|
327
|
-
structured: true,
|
|
328
|
-
};
|
|
347
|
+
if (!this.dataSelector) {
|
|
348
|
+
this.widget.selector.init(this.parentStore);
|
|
349
|
+
this.dataSelector = this.widget.selector.createStoreSelector();
|
|
329
350
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
this.
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
if (this.styled) this.prepareCSS(context, instance);
|
|
351
|
+
// init instance might change the store, so this must go before the controller initialization
|
|
352
|
+
this.widget.initInstance(context, this);
|
|
353
|
+
// initInstance can set the store, otherwise use parent store
|
|
354
|
+
if (!this.store) this.store = this.parentStore;
|
|
355
|
+
if (this.widget.onInit) this.widget.onInit(context, this);
|
|
356
|
+
this.widget.initState(context, this);
|
|
357
|
+
if (this.widget.controller)
|
|
358
|
+
this.controller = Controller.create(this.widget.controller, {
|
|
359
|
+
widget: this.widget,
|
|
360
|
+
instance: this,
|
|
361
|
+
store: this.store,
|
|
362
|
+
});
|
|
363
|
+
if (
|
|
364
|
+
this.widget.exploreCleanup ||
|
|
365
|
+
this.widget.outerLayout ||
|
|
366
|
+
this.widget.isContent ||
|
|
367
|
+
this.widget.controller ||
|
|
368
|
+
this.widget.prepareCleanup
|
|
369
|
+
)
|
|
370
|
+
this.needsExploreCleanup = true;
|
|
371
|
+
if (this.widget.prepare || this.widget.controller) this.needsPrepare = true;
|
|
372
|
+
if (this.widget.cleanup || this.widget.controller) this.needsCleanup = true;
|
|
373
|
+
this.initialized = true;
|
|
354
374
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
375
|
+
checkVisible(context) {
|
|
376
|
+
if (!this.initialized) this.init(context);
|
|
377
|
+
const wasVisible = this.visible;
|
|
378
|
+
this.rawData = this.dataSelector(this.store);
|
|
379
|
+
this.visible = this.widget.checkVisible(context, this, this.rawData);
|
|
380
|
+
if (this.visible && !this.detached) this.parent.instanceCache.addChild(this);
|
|
381
|
+
this.explored = false;
|
|
382
|
+
this.prepared = false;
|
|
383
|
+
if (!this.visible && wasVisible) this.destroy();
|
|
384
|
+
return this.visible;
|
|
359
385
|
}
|
|
360
|
-
|
|
361
|
-
if (this.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if (ins.scheduleExploreIfVisible(context)) instance.components[cmp] = ins;
|
|
366
|
-
}
|
|
386
|
+
scheduleExploreIfVisible(context) {
|
|
387
|
+
if (this.checkVisible(context)) {
|
|
388
|
+
context.exploreStack.push(this);
|
|
389
|
+
if (this.needsExploreCleanup) context.exploreStack.push(this);
|
|
390
|
+
return true;
|
|
367
391
|
}
|
|
392
|
+
return false;
|
|
368
393
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
update() {
|
|
376
|
-
this.version = (this.version || 0) + 1;
|
|
377
|
-
}
|
|
378
|
-
applyParentStore(instance) {
|
|
379
|
-
instance.store = instance.parentStore;
|
|
380
|
-
// check when this is actually needed, perhaps this is needed only for tables and repeated elements
|
|
381
|
-
// if (instance.cached) delete instance.cached.rawData; // force prepareData to execute again
|
|
394
|
+
cache(key, value) {
|
|
395
|
+
const oldValue = this.cached[key];
|
|
396
|
+
if (oldValue === value) return false;
|
|
397
|
+
if (!this.cacheList) this.cacheList = {};
|
|
398
|
+
this.cacheList[key] = value;
|
|
399
|
+
return true;
|
|
382
400
|
}
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
return true;
|
|
405
|
-
}
|
|
406
|
-
function getContentArray(x) {
|
|
407
|
-
let result = [];
|
|
408
|
-
contentAppend(result, x, false);
|
|
409
|
-
return result;
|
|
410
|
-
}
|
|
411
|
-
function getContent(x) {
|
|
412
|
-
let result = getContentArray(x);
|
|
413
|
-
if (result.length == 0) return null;
|
|
414
|
-
if (result.length == 1) return result[0];
|
|
415
|
-
return result;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
class StaticText extends Widget {
|
|
419
|
-
render() {
|
|
420
|
-
return this.text;
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
Widget.alias("static-text", StaticText);
|
|
424
|
-
|
|
425
|
-
class Text extends Widget {
|
|
426
|
-
constructor(config) {
|
|
427
|
-
super(config);
|
|
401
|
+
markShouldUpdate(context) {
|
|
402
|
+
let ins = this;
|
|
403
|
+
let renderList = this.renderList;
|
|
404
|
+
renderList.markReverseIndex();
|
|
405
|
+
//notify all parents that child state changed to bust up caching
|
|
406
|
+
while (ins && !ins.shouldUpdate && ins.explored) {
|
|
407
|
+
if (ins.renderList !== renderList) {
|
|
408
|
+
renderList.reverse();
|
|
409
|
+
renderList = ins.renderList;
|
|
410
|
+
renderList.markReverseIndex();
|
|
411
|
+
}
|
|
412
|
+
ins.shouldUpdate = true;
|
|
413
|
+
renderList.data.push(ins);
|
|
414
|
+
ins = ins.widget.isContent
|
|
415
|
+
? ins.contentPlaceholder
|
|
416
|
+
: ins.parent?.outerLayout === ins
|
|
417
|
+
? ins.parent?.parent
|
|
418
|
+
: ins.parent;
|
|
419
|
+
}
|
|
420
|
+
renderList.reverse();
|
|
428
421
|
}
|
|
429
|
-
|
|
430
|
-
if (!this.
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
422
|
+
explore(context) {
|
|
423
|
+
if (!this.visible) throw new Error("Explore invisible!");
|
|
424
|
+
if (this.explored) {
|
|
425
|
+
if (this.widget.prepareCleanup) context.prepareList.push(this);
|
|
426
|
+
if (this.widget.exploreCleanup) this.widget.exploreCleanup(context, this);
|
|
427
|
+
if (this.parent?.outerLayout === this) context.popNamedValue("content", "body");
|
|
428
|
+
if (this.widget.controller) context.pop("controller");
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
this.explored = true;
|
|
432
|
+
if (this.needsPrepare) context.prepareList.push(this);
|
|
433
|
+
else this.prepared = true;
|
|
434
|
+
if (this.needsCleanup) context.cleanupList.push(this);
|
|
435
|
+
if (this.instanceCache) this.instanceCache.mark();
|
|
436
|
+
//controller may reconfigure the widget and need to go before shouldUpdate calculation
|
|
437
|
+
this.parentOptions = context.parentOptions;
|
|
438
|
+
if (!this.controller) {
|
|
439
|
+
if (context.controller) this.controller = context.controller;
|
|
440
|
+
else if (this.parent?.controller) this.controller = this.parent?.controller;
|
|
441
|
+
}
|
|
442
|
+
this.destroyTracked = false;
|
|
443
|
+
if (this.controller) {
|
|
444
|
+
if (this.widget.controller) {
|
|
445
|
+
if (!this.controller.initialized) {
|
|
446
|
+
this.controller.init(context);
|
|
447
|
+
this.controller.initialized = true;
|
|
448
|
+
}
|
|
449
|
+
context.push("controller", this.controller);
|
|
450
|
+
this.controller.explore(context);
|
|
451
|
+
if (this.controller.onDestroy && this.controller.widget == this.widget) this.trackDestroy();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
if (this.widget.onDestroy || isNonEmptyArray(this.destroySubscriptions)) this.trackDestroy();
|
|
455
|
+
this.renderList = this.assignedRenderList || this.parent?.renderList || context.getRootRenderList();
|
|
456
|
+
let shouldUpdate =
|
|
457
|
+
this.rawData !== this.cached.rawData ||
|
|
458
|
+
this.state !== this.cached.state ||
|
|
459
|
+
this.widget.version !== this.cached.widgetVersion ||
|
|
460
|
+
this.cached.globalCacheIdentifier !== GlobalCacheIdentifier.get();
|
|
461
|
+
if (shouldUpdate) {
|
|
462
|
+
this.data = {
|
|
463
|
+
...this.rawData,
|
|
435
464
|
};
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
+
this.widget.prepareData(context, this);
|
|
466
|
+
debug(processDataFlag, this.widget);
|
|
467
|
+
}
|
|
468
|
+
//onExplore might set the outer layout
|
|
469
|
+
if (this.widget.onExplore) this.widget.onExplore(context, this);
|
|
470
|
+
if (this.parent?.outerLayout === this) {
|
|
471
|
+
this.renderList = this.renderList.insertRight();
|
|
472
|
+
context.pushNamedValue("content", "body", this.parent);
|
|
473
|
+
}
|
|
474
|
+
if (this.widget.outerLayout) {
|
|
475
|
+
this.outerLayout = this.getChild(context, this.widget.outerLayout, null, this.store);
|
|
476
|
+
this.outerLayout.scheduleExploreIfVisible(context);
|
|
477
|
+
this.renderList = this.renderList.insertLeft();
|
|
478
|
+
}
|
|
479
|
+
if (this.widget.isContent) {
|
|
480
|
+
this.contentPlaceholder = context.contentPlaceholder && context.contentPlaceholder[this.widget.putInto];
|
|
481
|
+
if (this.contentPlaceholder) context.contentPlaceholder[this.widget.putInto](this);
|
|
482
|
+
else {
|
|
483
|
+
this.renderList = this.renderList.insertLeft();
|
|
484
|
+
context.pushNamedValue("content", this.widget.putInto, this);
|
|
485
|
+
if (!context.contentList) context.contentList = {};
|
|
486
|
+
let list = context.contentList[this.widget.putInto];
|
|
487
|
+
if (!list) list = context.contentList[this.widget.putInto] = [];
|
|
488
|
+
list.push(this);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
this.shouldUpdate = false;
|
|
492
|
+
if (shouldUpdate || this.childStateDirty || !this.widget.memoize) this.markShouldUpdate(context);
|
|
493
|
+
context.exploreStack.hop();
|
|
494
|
+
if (this.widget.helpers) {
|
|
495
|
+
this.helpers = {};
|
|
496
|
+
for (let cmp in this.widget.helpers) {
|
|
497
|
+
let helper = this.widget.helpers[cmp];
|
|
498
|
+
if (helper) {
|
|
499
|
+
let ins = this.getChild(context, helper);
|
|
500
|
+
if (ins.scheduleExploreIfVisible(context)) this.helpers[cmp] = ins;
|
|
465
501
|
}
|
|
466
|
-
}
|
|
467
|
-
context.exploreStack.push(cell);
|
|
468
|
-
if (cell.needsExploreCleanup) context.exploreStack.push(cell);
|
|
502
|
+
}
|
|
469
503
|
}
|
|
504
|
+
//TODO: check do we need to pass data here?
|
|
505
|
+
this.widget.explore(context, this, this.data);
|
|
470
506
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
if (
|
|
479
|
-
if (this.
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
this.
|
|
483
|
-
if (this.
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
this.
|
|
492
|
-
} else {
|
|
493
|
-
this.add(layout);
|
|
494
|
-
this.layout = layout;
|
|
507
|
+
prepare(context) {
|
|
508
|
+
if (!this.visible) throw new Error("Prepare invisible!");
|
|
509
|
+
if (this.prepared) {
|
|
510
|
+
if (this.widget.prepareCleanup) this.widget.prepareCleanup(context, this);
|
|
511
|
+
return;
|
|
512
|
+
}
|
|
513
|
+
this.prepared = true;
|
|
514
|
+
if (this.widget.prepare) this.widget.prepare(context, this);
|
|
515
|
+
if (this.widget.controller && this.controller?.prepare) this.controller.prepare(context);
|
|
516
|
+
}
|
|
517
|
+
render(context) {
|
|
518
|
+
if (!this.visible) throw new Error("Render invisible!");
|
|
519
|
+
if (this.shouldUpdate) {
|
|
520
|
+
debug(renderFlag, this.widget, this.key);
|
|
521
|
+
const vdom = renderResultFix(this.widget.render(context, this, this.key));
|
|
522
|
+
if (this.widget.isContent || this.outerLayout) this.contentVDOM = vdom;
|
|
523
|
+
else this.vdom = vdom;
|
|
524
|
+
}
|
|
525
|
+
if (this.cacheList) {
|
|
526
|
+
for (const key in this.cacheList) {
|
|
527
|
+
this.cached[key] = this.cacheList[key];
|
|
495
528
|
}
|
|
496
|
-
} else {
|
|
497
|
-
this.add(items);
|
|
498
529
|
}
|
|
499
|
-
|
|
530
|
+
this.cacheList = null;
|
|
531
|
+
this.cached.rawData = this.rawData;
|
|
532
|
+
this.cached.data = this.data;
|
|
533
|
+
this.cached.state = this.state;
|
|
534
|
+
this.cached.widgetVersion = this.widget.version;
|
|
535
|
+
this.cached.globalCacheIdentifier = GlobalCacheIdentifier.get();
|
|
536
|
+
this.childStateDirty = false;
|
|
537
|
+
if (this.instanceCache) this.instanceCache.sweep();
|
|
538
|
+
if (this.parent?.outerLayout === this) {
|
|
539
|
+
//if outer layouts are chained we need to find the originating element (last element with OL set)
|
|
540
|
+
let parent = this.parent;
|
|
541
|
+
while (parent.parent?.outerLayout == parent) parent = parent.parent;
|
|
542
|
+
parent.vdom = this.vdom;
|
|
543
|
+
}
|
|
544
|
+
return this.vdom;
|
|
500
545
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if (
|
|
546
|
+
cleanup(context) {
|
|
547
|
+
if (this.widget.controller && this.controller?.cleanup) this.controller.cleanup(context);
|
|
548
|
+
if (this.widget.cleanup) this.widget.cleanup(context, this);
|
|
504
549
|
}
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
550
|
+
trackDestroy() {
|
|
551
|
+
if (!this.destroyTracked) {
|
|
552
|
+
this.destroyTracked = true;
|
|
553
|
+
if (this.parent && !this.detached) this.parent.trackDestroyableChild(this);
|
|
554
|
+
}
|
|
508
555
|
}
|
|
509
|
-
|
|
510
|
-
|
|
556
|
+
trackDestroyableChild(child) {
|
|
557
|
+
this.instanceCache.trackDestroy(child);
|
|
558
|
+
this.trackDestroy();
|
|
511
559
|
}
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
if (
|
|
518
|
-
|
|
519
|
-
return;
|
|
520
|
-
}
|
|
521
|
-
if (r.useParentLayout) return r.content.forEach((x) => append(result, x));
|
|
522
|
-
if (r.atomic || preserveComplexContent) {
|
|
523
|
-
result.push(r);
|
|
524
|
-
} else {
|
|
525
|
-
let first = true;
|
|
526
|
-
for (let k in r) if (contentAppend(result, r[k], !first)) first = false;
|
|
560
|
+
subscribeOnDestroy(callback) {
|
|
561
|
+
if (!this.destroySubscriptions) this.destroySubscriptions = [];
|
|
562
|
+
this.destroySubscriptions.push(callback);
|
|
563
|
+
this.trackDestroy();
|
|
564
|
+
return () => {
|
|
565
|
+
if (this.destroySubscriptions) {
|
|
566
|
+
this.destroySubscriptions = this.destroySubscriptions.filter((cb) => cb !== callback);
|
|
527
567
|
}
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
destroy() {
|
|
571
|
+
if (this.instanceCache) {
|
|
572
|
+
this.instanceCache.destroy();
|
|
573
|
+
this.instanceCache = null;
|
|
528
574
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
575
|
+
if (this.destroySubscriptions) {
|
|
576
|
+
this.destroySubscriptions.forEach((cb) => cb());
|
|
577
|
+
this.destroySubscriptions = null;
|
|
578
|
+
}
|
|
579
|
+
if (this.destroyTracked) {
|
|
580
|
+
debug(destroyFlag, this);
|
|
581
|
+
if (this.widget.onDestroy) this.widget.onDestroy(this);
|
|
582
|
+
if (
|
|
583
|
+
this.widget.controller &&
|
|
584
|
+
this.controller &&
|
|
585
|
+
this.controller.onDestroy &&
|
|
586
|
+
this.controller.widget == this.widget
|
|
587
|
+
)
|
|
588
|
+
this.controller.onDestroy();
|
|
589
|
+
this.destroyTracked = false;
|
|
532
590
|
}
|
|
533
|
-
if (this.useParentLayout)
|
|
534
|
-
return {
|
|
535
|
-
useParentLayout: true,
|
|
536
|
-
content: result,
|
|
537
|
-
};
|
|
538
|
-
return result;
|
|
539
591
|
}
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
592
|
+
setState(state) {
|
|
593
|
+
let skip = !!this.state;
|
|
594
|
+
if (this.state) {
|
|
595
|
+
for (const k in state) {
|
|
596
|
+
if (this.state[k] !== state[k]) {
|
|
597
|
+
skip = false;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
if (skip) return;
|
|
603
|
+
this.state = Object.assign({}, this.state, state);
|
|
604
|
+
let parent = this.parent;
|
|
605
|
+
//notify all parents that child state change to bust up caching
|
|
606
|
+
while (parent) {
|
|
607
|
+
parent.childStateDirty = true;
|
|
608
|
+
parent = parent.parent;
|
|
609
|
+
}
|
|
610
|
+
batchUpdates(() => {
|
|
611
|
+
this.store.notify();
|
|
612
|
+
});
|
|
543
613
|
}
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
614
|
+
set(prop, value, options = {}) {
|
|
615
|
+
//skip re-rendering (used for reading state from uncontrolled components)
|
|
616
|
+
if (options.internal && this.rawData) {
|
|
617
|
+
this.rawData[prop] = value;
|
|
618
|
+
this.data[prop] = value;
|
|
619
|
+
}
|
|
620
|
+
const setter = this.setters && this.setters[prop];
|
|
621
|
+
if (setter) {
|
|
622
|
+
if (options.immediate && isFunction(setter.reset)) setter.reset(value);
|
|
623
|
+
else setter(value);
|
|
624
|
+
return true;
|
|
625
|
+
}
|
|
626
|
+
const p = this.widget[prop];
|
|
627
|
+
if (p && typeof p == "object") {
|
|
628
|
+
if (p.debounce) {
|
|
629
|
+
this.definePropertySetter(
|
|
630
|
+
prop,
|
|
631
|
+
validatedDebounce(
|
|
632
|
+
(value) => this.doSet(prop, value),
|
|
633
|
+
() => this.dataSelector(this.store)[prop],
|
|
634
|
+
p.debounce,
|
|
635
|
+
),
|
|
636
|
+
);
|
|
637
|
+
this.set(prop, value, options);
|
|
638
|
+
return true;
|
|
639
|
+
}
|
|
640
|
+
if (p.throttle) {
|
|
641
|
+
this.definePropertySetter(
|
|
642
|
+
prop,
|
|
643
|
+
throttle((value) => this.doSet(prop, value), p.throttle),
|
|
644
|
+
);
|
|
645
|
+
this.set(prop, value, options);
|
|
646
|
+
return true;
|
|
556
647
|
}
|
|
557
648
|
}
|
|
649
|
+
return this.doSet(prop, value);
|
|
558
650
|
}
|
|
559
|
-
|
|
560
|
-
|
|
651
|
+
definePropertySetter(prop, setter) {
|
|
652
|
+
if (!this.setters) this.setters = {};
|
|
653
|
+
this.setters[prop] = setter;
|
|
561
654
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
655
|
+
doSet(prop, value) {
|
|
656
|
+
let changed = false;
|
|
657
|
+
batchUpdates(() => {
|
|
658
|
+
const p = this.widget[prop];
|
|
659
|
+
if (isObject(p)) {
|
|
660
|
+
const pObj = p;
|
|
661
|
+
if (pObj.set) {
|
|
662
|
+
if (isFunction(pObj.set)) {
|
|
663
|
+
pObj.set(value, this);
|
|
664
|
+
changed = true;
|
|
665
|
+
} else if (isString(pObj.set)) {
|
|
666
|
+
this.controller?.[pObj.set](value, this);
|
|
667
|
+
changed = true;
|
|
668
|
+
}
|
|
669
|
+
} else if (pObj.action) {
|
|
670
|
+
const action = pObj.action(value, this);
|
|
671
|
+
this.store.dispatch(action);
|
|
672
|
+
changed = true;
|
|
673
|
+
} else if (isString(pObj.bind) || isAccessorChain(pObj.bind)) {
|
|
674
|
+
changed = this.store.set(pObj.bind, value);
|
|
675
|
+
}
|
|
676
|
+
} else if (isAccessorChain(p)) {
|
|
677
|
+
changed = this.store.set(p.toString(), value);
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
return changed;
|
|
681
|
+
}
|
|
682
|
+
nestedDataSet(key, value, dataConfig, useParentStore) {
|
|
683
|
+
let config = dataConfig[key];
|
|
684
|
+
if (!config)
|
|
685
|
+
throw new Error(`Unknown nested data key ${key}. Known keys are ${Object.keys(dataConfig).join(", ")}.`);
|
|
686
|
+
if (isAccessorChain(config))
|
|
687
|
+
config = {
|
|
688
|
+
bind: config.toString(),
|
|
689
|
+
};
|
|
690
|
+
if (config.bind) {
|
|
691
|
+
let store = this.store;
|
|
692
|
+
//in case of Rescope or DataProxy, bindings point to the data in the parent store
|
|
693
|
+
if (useParentStore && store.store) store = store.store;
|
|
694
|
+
return isUndefined(value) ? store.deleteItem(config.bind) : store.setItem(config.bind, value);
|
|
695
|
+
}
|
|
696
|
+
if (!config.set)
|
|
697
|
+
throw new Error(
|
|
698
|
+
`Cannot change nested data value for ${key} as it's read-only. Either define it as a binding or define a set function.`,
|
|
572
699
|
);
|
|
700
|
+
if (isString(config.set)) this.getControllerMethod(config.set)(value, this);
|
|
701
|
+
else if (isFunction(config.set)) config.set(value, this);
|
|
573
702
|
else
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
Text,
|
|
577
|
-
{
|
|
578
|
-
text: {
|
|
579
|
-
tpl: text,
|
|
580
|
-
},
|
|
581
|
-
},
|
|
582
|
-
{},
|
|
583
|
-
),
|
|
703
|
+
throw new Error(
|
|
704
|
+
`Cannot change nested data value for ${key} the defined setter is neither a function nor a controller method.`,
|
|
584
705
|
);
|
|
706
|
+
return true;
|
|
585
707
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
if (isString(filter)) filter = (w) => w.componentAlias == alias;
|
|
591
|
-
if (filter.isComponentType) filter = (w) => w instanceof alias;
|
|
592
|
-
let results = [];
|
|
593
|
-
for (let i = 0; i < this.items.length; i++) {
|
|
594
|
-
let w = this.items[i];
|
|
595
|
-
if (w && !w.initialized) w.init();
|
|
596
|
-
if (filter(w)) {
|
|
597
|
-
results.push(w);
|
|
598
|
-
if (options.first) break;
|
|
599
|
-
}
|
|
600
|
-
if (w && w.find) results.push(...w.find(filter, options));
|
|
601
|
-
}
|
|
602
|
-
return results;
|
|
603
|
-
}
|
|
604
|
-
findFirst(filter, options) {
|
|
605
|
-
return this.find(filter, {
|
|
606
|
-
...options,
|
|
607
|
-
first: true,
|
|
608
|
-
})[0];
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
ContainerBase.prototype.trimWhitespace = true;
|
|
612
|
-
ContainerBase.prototype.plainText = true;
|
|
613
|
-
ContainerBase.prototype.styled = false;
|
|
614
|
-
// Closed type for direct usage - preserves ControllerProp ThisType
|
|
615
|
-
class Container extends ContainerBase {}
|
|
616
|
-
// Base class for styled containers with custom Config types
|
|
617
|
-
class StyledContainerBase extends ContainerBase {}
|
|
618
|
-
StyledContainerBase.prototype.styled = true;
|
|
619
|
-
// Closed type for direct usage
|
|
620
|
-
class StyledContainer extends StyledContainerBase {}
|
|
621
|
-
|
|
622
|
-
// Base class for extending with custom Config types
|
|
623
|
-
class PureContainerBase extends ContainerBase {}
|
|
624
|
-
PureContainerBase.prototype.isPureContainer = true;
|
|
625
|
-
// Closed type for direct usage - preserves ControllerProp ThisType
|
|
626
|
-
class PureContainer extends PureContainerBase {}
|
|
627
|
-
PureContainer.alias("pure-container", PureContainer);
|
|
628
|
-
|
|
629
|
-
class DataAdapter extends Component {
|
|
630
|
-
constructor(config) {
|
|
631
|
-
super(config);
|
|
708
|
+
replaceState(state) {
|
|
709
|
+
this.cached.state = this.state;
|
|
710
|
+
this.state = state;
|
|
711
|
+
this.store.notify();
|
|
632
712
|
}
|
|
633
|
-
|
|
634
|
-
this.
|
|
713
|
+
getInstanceCache() {
|
|
714
|
+
if (!this.instanceCache)
|
|
715
|
+
this.instanceCache = new InstanceCache(this, this.widget.isPureContainer ? this.key : null);
|
|
716
|
+
return this.instanceCache;
|
|
635
717
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
DataAdapter.prototype.recordName = "$record";
|
|
639
|
-
DataAdapter.prototype.indexName = "$index";
|
|
640
|
-
DataAdapter.prototype.immutable = false;
|
|
641
|
-
|
|
642
|
-
let contents = {};
|
|
643
|
-
let localizations = {};
|
|
644
|
-
let overrides = {};
|
|
645
|
-
let defaults = {};
|
|
646
|
-
let trackDefaults = false;
|
|
647
|
-
class Localization {
|
|
648
|
-
static register(key) {
|
|
649
|
-
return (type) => {
|
|
650
|
-
this.registerPrototype(key, type);
|
|
651
|
-
return type;
|
|
652
|
-
};
|
|
718
|
+
clearChildrenCache() {
|
|
719
|
+
if (this.instanceCache) this.instanceCache.destroy();
|
|
653
720
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
if (overrides[key]) this.override(key, overrides[key]);
|
|
721
|
+
getChild(context, widget, key, store) {
|
|
722
|
+
return this.getInstanceCache().getChild(widget, store ?? this.store, key);
|
|
657
723
|
}
|
|
658
|
-
|
|
659
|
-
|
|
724
|
+
getDetachedChild(widget, key, store) {
|
|
725
|
+
const child = widget.createInstance(key, this, store ?? this.store);
|
|
726
|
+
child.detached = true;
|
|
727
|
+
return child;
|
|
660
728
|
}
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
let proto = contents[type];
|
|
664
|
-
if (!proto) continue;
|
|
665
|
-
let d = defaults[type];
|
|
666
|
-
for (let key in d) proto[key] = d[key];
|
|
667
|
-
}
|
|
668
|
-
defaults = {};
|
|
729
|
+
prepareRenderCleanupChild(widget, store, keyPrefix, options) {
|
|
730
|
+
return widget.prepareRenderCleanup(store ?? this.store, options, keyPrefix, this);
|
|
669
731
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
732
|
+
getJsxEventProps() {
|
|
733
|
+
const { widget } = this;
|
|
734
|
+
if (!isArray(widget.jsxAttributes)) return null;
|
|
735
|
+
const props = {};
|
|
736
|
+
widget.jsxAttributes.forEach((attr) => {
|
|
737
|
+
if (attr.indexOf("on") == 0 && attr.length > 2) {
|
|
738
|
+
props[attr] = (e) => this.invoke(attr, e, this);
|
|
677
739
|
}
|
|
678
|
-
|
|
679
|
-
|
|
740
|
+
});
|
|
741
|
+
return props;
|
|
680
742
|
}
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
743
|
+
getCallback(methodName) {
|
|
744
|
+
const scope = this.widget;
|
|
745
|
+
const callback = scope[methodName];
|
|
746
|
+
if (typeof callback === "string") return this.getControllerMethod(callback);
|
|
747
|
+
if (typeof callback !== "function")
|
|
748
|
+
throw new Error(`Cannot invoke callback method ${methodName} as assigned value is not a function.`);
|
|
749
|
+
return callback.bind(scope);
|
|
688
750
|
}
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
751
|
+
/**
|
|
752
|
+
* Finds the first controller in the instance tree matching the predicate
|
|
753
|
+
* @param predicate Function to test each controller
|
|
754
|
+
* @returns The matching controller or undefined
|
|
755
|
+
*/
|
|
756
|
+
findController(predicate) {
|
|
757
|
+
let at = this;
|
|
758
|
+
while (at?.controller != null) {
|
|
759
|
+
if (predicate(at.controller)) {
|
|
760
|
+
return at.controller;
|
|
695
761
|
}
|
|
762
|
+
at = at.parent;
|
|
696
763
|
}
|
|
764
|
+
return undefined;
|
|
697
765
|
}
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
dateTimeCulture: null,
|
|
706
|
-
cache: {},
|
|
707
|
-
defaultCurrency: "USD",
|
|
708
|
-
dateEncoding: (date) => date.toISOString(),
|
|
709
|
-
timezone: null,
|
|
710
|
-
},
|
|
711
|
-
];
|
|
712
|
-
function getDefaultCulture() {
|
|
713
|
-
return stack[0];
|
|
714
|
-
}
|
|
715
|
-
function getCurrentCulture() {
|
|
716
|
-
return stack[stack.length - 1];
|
|
717
|
-
}
|
|
718
|
-
function getCurrentCultureCache() {
|
|
719
|
-
return getCurrentCulture().cache;
|
|
720
|
-
}
|
|
721
|
-
function pushCulture(cultureInfo) {
|
|
722
|
-
stack.push(cultureInfo);
|
|
723
|
-
}
|
|
724
|
-
function createCulture(cultureSpecs) {
|
|
725
|
-
let current = getCurrentCulture();
|
|
726
|
-
let info = {
|
|
727
|
-
culture: current.culture,
|
|
728
|
-
dateEncoding: current.dateEncoding,
|
|
729
|
-
defaultCurrency: current.defaultCurrency,
|
|
730
|
-
cache: {},
|
|
731
|
-
};
|
|
732
|
-
for (let key in cultureSpecs) {
|
|
733
|
-
if (!cultureSpecs[key]) continue;
|
|
734
|
-
info[key] = cultureSpecs[key];
|
|
735
|
-
}
|
|
736
|
-
return info;
|
|
737
|
-
}
|
|
738
|
-
function popCulture(cultureSpecs) {
|
|
739
|
-
if (stack.length == 1) throw new Error("Cannot pop the last culture object.");
|
|
740
|
-
if (cultureSpecs && stack[stack.length - 1] !== cultureSpecs) {
|
|
741
|
-
Console.warn("Popped culture object does not match the current one.");
|
|
742
|
-
}
|
|
743
|
-
return stack.pop();
|
|
744
|
-
}
|
|
745
|
-
class Culture {
|
|
746
|
-
static setCulture(cultureCode) {
|
|
747
|
-
let cultureSpecs = getDefaultCulture();
|
|
748
|
-
cultureSpecs.culture = cultureCode;
|
|
749
|
-
cultureSpecs.cache = {};
|
|
750
|
-
Localization.setCulture(cultureCode);
|
|
751
|
-
this.invalidateCache();
|
|
752
|
-
}
|
|
753
|
-
static setNumberCulture(cultureCode) {
|
|
754
|
-
let cultureSpecs = getDefaultCulture();
|
|
755
|
-
cultureSpecs.numberCulture = cultureCode;
|
|
756
|
-
delete cultureSpecs.cache.numberCulture;
|
|
757
|
-
this.invalidateCache();
|
|
766
|
+
/**
|
|
767
|
+
* Finds a controller of the specified type in the instance tree
|
|
768
|
+
* @param type Controller class/constructor to find
|
|
769
|
+
* @returns The matching controller cast to the specified type, or undefined
|
|
770
|
+
*/
|
|
771
|
+
findControllerByType(type) {
|
|
772
|
+
return this.findController((c) => c instanceof type);
|
|
758
773
|
}
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
774
|
+
/**
|
|
775
|
+
* Gets the first controller in the instance tree matching the predicate
|
|
776
|
+
* @param predicate Function to test each controller
|
|
777
|
+
* @returns The matching controller
|
|
778
|
+
* @throws Error if no matching controller is found
|
|
779
|
+
*/
|
|
780
|
+
getController(predicate) {
|
|
781
|
+
const controller = this.findController(predicate);
|
|
782
|
+
if (!controller) throw new Error("Cannot find a controller matching the given predicate in the instance tree.");
|
|
783
|
+
return controller;
|
|
764
784
|
}
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
785
|
+
/**
|
|
786
|
+
* Gets a controller of the specified type in the instance tree
|
|
787
|
+
* @param type Controller class/constructor to find
|
|
788
|
+
* @returns The matching controller cast to the specified type
|
|
789
|
+
* @throws Error if no controller of the specified type is found
|
|
790
|
+
*/
|
|
791
|
+
getControllerByType(type) {
|
|
792
|
+
const controller = this.findControllerByType(type);
|
|
793
|
+
if (!controller) throw new Error(`Cannot find a controller of type "${type.name}" in the instance tree.`);
|
|
794
|
+
return controller;
|
|
769
795
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
this.
|
|
796
|
+
getControllerMethod(methodName) {
|
|
797
|
+
if (!this.controller)
|
|
798
|
+
throw new Error(`Cannot invoke controller method "${methodName}" as controller is not assigned to the widget.`);
|
|
799
|
+
const controller = this.findController((c) => !!c[methodName]);
|
|
800
|
+
if (!controller)
|
|
801
|
+
throw new Error(
|
|
802
|
+
`Cannot invoke controller method "${methodName}". The method cannot be found in any of the assigned controllers.`,
|
|
803
|
+
);
|
|
804
|
+
return controller[methodName].bind(controller);
|
|
774
805
|
}
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
cultureSpecs.dateEncoding = encoding;
|
|
778
|
-
this.invalidateCache();
|
|
806
|
+
invoke(methodName, ...args) {
|
|
807
|
+
return this.getCallback(methodName).apply(null, args);
|
|
779
808
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
invalidateExpressionCache();
|
|
783
|
-
invalidateStringTemplateCache();
|
|
809
|
+
invokeControllerMethod(methodName, ...args) {
|
|
810
|
+
return this.getControllerMethod(methodName).apply(null, args);
|
|
784
811
|
}
|
|
785
|
-
|
|
786
|
-
|
|
812
|
+
}
|
|
813
|
+
function renderResultFix(res) {
|
|
814
|
+
return res != null && isDefined(res.content)
|
|
815
|
+
? res
|
|
816
|
+
: {
|
|
817
|
+
content: res,
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
class InstanceCache {
|
|
821
|
+
constructor(parent, keyPrefix) {
|
|
822
|
+
this.children = {};
|
|
823
|
+
this.parent = parent;
|
|
824
|
+
this.marked = {};
|
|
825
|
+
this.monitored = null;
|
|
826
|
+
this.keyPrefix = keyPrefix != null ? keyPrefix + "-" : "";
|
|
787
827
|
}
|
|
788
|
-
|
|
789
|
-
|
|
828
|
+
getChild(widget, parentStore, key) {
|
|
829
|
+
const k = this.keyPrefix + (key != null ? key : widget.vdomKey || widget.widgetId);
|
|
830
|
+
let instance = this.children[k];
|
|
831
|
+
if (
|
|
832
|
+
!instance ||
|
|
833
|
+
instance.widget !== widget ||
|
|
834
|
+
(!instance.visible && (instance.widget.controller || instance.widget.onInit))
|
|
835
|
+
) {
|
|
836
|
+
instance = widget.createInstance(k, this.parent, parentStore);
|
|
837
|
+
this.children[k] = instance;
|
|
838
|
+
} else if (instance.parentStore !== parentStore) {
|
|
839
|
+
instance.setParentStore(parentStore);
|
|
840
|
+
}
|
|
841
|
+
return instance;
|
|
790
842
|
}
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
if (!cache.numberCulture) cache.numberCulture = new NumberCulture(numberCulture ?? culture);
|
|
794
|
-
return cache.numberCulture;
|
|
843
|
+
addChild(instance) {
|
|
844
|
+
this.marked[instance.key] = instance;
|
|
795
845
|
}
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
if (!cache.dateTimeCulture)
|
|
799
|
-
cache.dateTimeCulture = new DateTimeCulture(dateTimeCulture ?? culture, {
|
|
800
|
-
defaultTimezone: timezone,
|
|
801
|
-
});
|
|
802
|
-
return cache.dateTimeCulture;
|
|
846
|
+
mark() {
|
|
847
|
+
this.marked = {};
|
|
803
848
|
}
|
|
804
|
-
|
|
805
|
-
|
|
849
|
+
trackDestroy(instance) {
|
|
850
|
+
if (!this.monitored) this.monitored = {};
|
|
851
|
+
this.monitored[instance.key] = instance;
|
|
806
852
|
}
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
return
|
|
853
|
+
destroy() {
|
|
854
|
+
this.children = {};
|
|
855
|
+
this.marked = {};
|
|
856
|
+
if (!this.monitored) return;
|
|
857
|
+
for (const key in this.monitored) {
|
|
858
|
+
this.monitored[key].destroy();
|
|
859
|
+
}
|
|
860
|
+
this.monitored = null;
|
|
861
|
+
}
|
|
862
|
+
sweep() {
|
|
863
|
+
this.children = this.marked;
|
|
864
|
+
if (!this.monitored) return;
|
|
865
|
+
let activeCount = 0;
|
|
866
|
+
for (const key in this.monitored) {
|
|
867
|
+
const monitoredChild = this.monitored[key];
|
|
868
|
+
const child = this.children[key];
|
|
869
|
+
if (child !== monitoredChild || !monitoredChild.visible) {
|
|
870
|
+
monitoredChild.destroy();
|
|
871
|
+
delete this.monitored[key];
|
|
872
|
+
if (child === monitoredChild) delete this.children[key];
|
|
873
|
+
} else activeCount++;
|
|
874
|
+
}
|
|
875
|
+
if (activeCount === 0) this.monitored = null;
|
|
811
876
|
}
|
|
812
877
|
}
|
|
813
878
|
|
|
814
|
-
|
|
879
|
+
const VDOM = VDOM$1;
|
|
880
|
+
let widgetId = 100;
|
|
881
|
+
class Widget extends Component {
|
|
882
|
+
// runtime values
|
|
883
|
+
widgetId;
|
|
884
|
+
initialized;
|
|
885
|
+
components;
|
|
886
|
+
helpers;
|
|
887
|
+
selector;
|
|
888
|
+
nameMap;
|
|
889
|
+
version;
|
|
890
|
+
static optimizePrepare;
|
|
815
891
|
constructor(config) {
|
|
816
892
|
super(config);
|
|
893
|
+
this.widgetId = widgetId++;
|
|
894
|
+
if (isArray(this.jsxSpread)) {
|
|
895
|
+
if (!this.jsxAttributes) this.jsxAttributes = [];
|
|
896
|
+
this.jsxSpread.forEach((spread) => {
|
|
897
|
+
for (const key in spread) {
|
|
898
|
+
this[key] = spread[key];
|
|
899
|
+
this.jsxAttributes.push(key);
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
}
|
|
817
903
|
}
|
|
818
904
|
init() {
|
|
819
|
-
|
|
820
|
-
this.
|
|
821
|
-
this.
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
}
|
|
828
|
-
if (!instance.recordsAccessor && this.recordsAccessor) {
|
|
829
|
-
instance.recordsAccessor = this.recordsAccessor.bindInstance
|
|
830
|
-
? this.recordsAccessor.bindInstance(instance)
|
|
831
|
-
: this.recordsAccessor;
|
|
905
|
+
if (this.styles) this.style = this.styles;
|
|
906
|
+
if (this.styled) this.style = parseStyle(this.style);
|
|
907
|
+
if (typeof this.if !== "undefined") this.visible = this.if;
|
|
908
|
+
this.declareData();
|
|
909
|
+
if (this.outerLayout) {
|
|
910
|
+
if (isArray(this.outerLayout)) throw new Error("Only single element outer layout is supported.");
|
|
911
|
+
//TODO: better handle the case when outer layout is an array. How to get around circular dependency to PureContainer
|
|
912
|
+
this.outerLayout = Widget.create(this.outerLayout, {});
|
|
832
913
|
}
|
|
914
|
+
if (this.contentFor) this.putInto = this.contentFor;
|
|
915
|
+
if (this.putInto) this.isContent = true;
|
|
916
|
+
if (isString(this.CSS)) this.CSS = CSSHelper.get(this.CSS);
|
|
917
|
+
this.initHelpers();
|
|
918
|
+
this.initComponents();
|
|
919
|
+
this.initialized = true;
|
|
833
920
|
}
|
|
834
|
-
|
|
835
|
-
if (
|
|
836
|
-
this.
|
|
921
|
+
initComponents(...args) {
|
|
922
|
+
if (args.length > 0) {
|
|
923
|
+
this.components = Object.assign({}, ...args);
|
|
924
|
+
for (const k in this.components) {
|
|
925
|
+
if (!this.components[k]) delete this.components[k];
|
|
926
|
+
}
|
|
837
927
|
}
|
|
838
|
-
return this.mapRecords(context, instance, records, parentStore, instance.recordsAccessor);
|
|
839
928
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
this.initInstance(context, instance);
|
|
844
|
-
}
|
|
845
|
-
if (isArray(records)) {
|
|
846
|
-
records.forEach((data, index) => {
|
|
847
|
-
if (this.filterFn && !this.filterFn(data)) return;
|
|
848
|
-
const record = this.mapRecord(context, instance, data, parentStore, recordsAccessor, index);
|
|
849
|
-
result.push(record);
|
|
850
|
-
});
|
|
851
|
-
}
|
|
852
|
-
if (this.sorter && !this.preserveOrder) {
|
|
853
|
-
result = this.sorter(result);
|
|
929
|
+
initHelpers(...args) {
|
|
930
|
+
if (args.length > 0) {
|
|
931
|
+
this.helpers = Object.assign({}, ...args);
|
|
854
932
|
}
|
|
855
|
-
return result;
|
|
856
933
|
}
|
|
857
|
-
|
|
858
|
-
const
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
recordAlias: this.recordName,
|
|
867
|
-
indexAlias: this.indexName,
|
|
868
|
-
immutable: this.immutable,
|
|
869
|
-
sealed: this.sealed,
|
|
870
|
-
});
|
|
871
|
-
} else {
|
|
872
|
-
recordStore.setStore(parentStore);
|
|
873
|
-
recordStore.setIndex(index);
|
|
874
|
-
}
|
|
875
|
-
} else {
|
|
876
|
-
if (!recordStore) {
|
|
877
|
-
recordStore = new ReadOnlyDataView({
|
|
878
|
-
store: parentStore,
|
|
879
|
-
data: {
|
|
880
|
-
[this.recordName]: data,
|
|
881
|
-
[this.indexName]: index,
|
|
882
|
-
},
|
|
883
|
-
immutable: this.immutable,
|
|
884
|
-
sealed: this.sealed,
|
|
885
|
-
});
|
|
886
|
-
} else {
|
|
887
|
-
recordStore.setStore(parentStore);
|
|
888
|
-
recordStore.setData({
|
|
889
|
-
[this.recordName]: data,
|
|
890
|
-
[this.indexName]: index,
|
|
891
|
-
});
|
|
892
|
-
}
|
|
893
|
-
}
|
|
894
|
-
if (key != null) {
|
|
895
|
-
instance.cacheByKey[key] = recordStore;
|
|
896
|
-
} else if (isObject(data)) {
|
|
897
|
-
instance.recordStoreCache.set(data, recordStore);
|
|
934
|
+
declareData(...args) {
|
|
935
|
+
const options = {};
|
|
936
|
+
if (this.styled) {
|
|
937
|
+
options.class =
|
|
938
|
+
options.className =
|
|
939
|
+
options.style =
|
|
940
|
+
{
|
|
941
|
+
structured: true,
|
|
942
|
+
};
|
|
898
943
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
944
|
+
const props = {
|
|
945
|
+
visible: undefined,
|
|
946
|
+
mod: {
|
|
947
|
+
structured: true,
|
|
948
|
+
},
|
|
949
|
+
...options,
|
|
905
950
|
};
|
|
951
|
+
Object.assign(props, ...args);
|
|
952
|
+
this.selector = new StructuredSelector({
|
|
953
|
+
props: props,
|
|
954
|
+
values: this,
|
|
955
|
+
});
|
|
956
|
+
this.nameMap = this.selector.nameMap;
|
|
906
957
|
}
|
|
907
|
-
|
|
908
|
-
|
|
958
|
+
prepareCSS(_context, { data }) {
|
|
959
|
+
data.classNames = this.CSS.expand(
|
|
960
|
+
this.CSS.block(this.baseClass, data.mod, data.stateMods),
|
|
961
|
+
data.class,
|
|
962
|
+
data.className,
|
|
963
|
+
);
|
|
964
|
+
data.style = parseStyle(data.style);
|
|
909
965
|
}
|
|
910
|
-
|
|
911
|
-
|
|
966
|
+
prepareData(context, instance) {
|
|
967
|
+
if (this.styled) this.prepareCSS(context, instance);
|
|
912
968
|
}
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
969
|
+
createInstance(key, parent, parentStore) {
|
|
970
|
+
return new Instance(this, key, parent, parentStore);
|
|
971
|
+
}
|
|
972
|
+
initInstance(_context, _instance) {}
|
|
973
|
+
initState(_context, _instance) {}
|
|
974
|
+
checkVisible(_context, _instance, data) {
|
|
975
|
+
return data.visible;
|
|
976
|
+
}
|
|
977
|
+
explore(context, instance, data) {
|
|
978
|
+
if (this.components) {
|
|
979
|
+
instance.components = {};
|
|
980
|
+
for (const cmp in this.components) {
|
|
981
|
+
const ins = instance.getChild(context, this.components[cmp], "cmp-" + cmp, instance.store);
|
|
982
|
+
if (ins.scheduleExploreIfVisible(context)) instance.components[cmp] = ins;
|
|
927
983
|
}
|
|
928
|
-
this.sorter = sorter(
|
|
929
|
-
sorters.map((x) => {
|
|
930
|
-
const s = Object.assign({}, x);
|
|
931
|
-
if (s.field && s.value == null) {
|
|
932
|
-
s.value = fieldValueMapper(s);
|
|
933
|
-
}
|
|
934
|
-
if (!s.comparer) {
|
|
935
|
-
s.comparer = this.getComparer(isDefined(s.sortOptions) ? s.sortOptions : this.sortOptions);
|
|
936
|
-
}
|
|
937
|
-
return s;
|
|
938
|
-
}),
|
|
939
|
-
dataAccessor,
|
|
940
|
-
);
|
|
941
|
-
} else {
|
|
942
|
-
this.sorter = undefined;
|
|
943
984
|
}
|
|
944
985
|
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
986
|
+
render(context, instance, key) {
|
|
987
|
+
Console.log(this);
|
|
988
|
+
throw new Error(
|
|
989
|
+
'Widget\'s render method should be overridden. This error usually happens if with incorrect imports, i.e. import { TextField } from "cx/data". Please check the console for details about the component configuration.',
|
|
990
|
+
);
|
|
991
|
+
}
|
|
992
|
+
update() {
|
|
993
|
+
this.version = (this.version || 0) + 1;
|
|
994
|
+
}
|
|
995
|
+
applyParentStore(instance) {
|
|
996
|
+
instance.store = instance.parentStore;
|
|
997
|
+
// check when this is actually needed, perhaps this is needed only for tables and repeated elements
|
|
998
|
+
// if (instance.cached) delete instance.cached.rawData; // force prepareData to execute again
|
|
999
|
+
}
|
|
1000
|
+
static resetCounter() {
|
|
1001
|
+
widgetId = 100;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
Widget.prototype.visible = true;
|
|
1005
|
+
Widget.prototype.memoize = true; //cache rendered content and use it if possible
|
|
1006
|
+
Widget.prototype.CSS = CSS;
|
|
1007
|
+
Widget.prototype.styled = false;
|
|
1008
|
+
Widget.namespace = "ui.";
|
|
1009
|
+
Widget.optimizePrepare = true;
|
|
1010
|
+
Widget.factory = (type, _config, _more) => {
|
|
1011
|
+
throw new Error(`Invalid widget type: ${type}.`);
|
|
1012
|
+
};
|
|
1013
|
+
function contentAppend(result, w, prependSpace) {
|
|
1014
|
+
if (w == null || w === false) return false;
|
|
1015
|
+
if (isArray(w)) w.forEach((c) => contentAppend(result, c));
|
|
1016
|
+
else if (isDefined(w.content) && !w.atomic) return contentAppend(result, w.content, false);
|
|
1017
|
+
else {
|
|
1018
|
+
if (prependSpace) result.push(" ");
|
|
1019
|
+
result.push(w);
|
|
949
1020
|
}
|
|
1021
|
+
return true;
|
|
1022
|
+
}
|
|
1023
|
+
function getContentArray(x) {
|
|
1024
|
+
let result = [];
|
|
1025
|
+
contentAppend(result, x, false);
|
|
1026
|
+
return result;
|
|
1027
|
+
}
|
|
1028
|
+
function getContent(x) {
|
|
1029
|
+
let result = getContentArray(x);
|
|
1030
|
+
if (result.length == 0) return null;
|
|
1031
|
+
if (result.length == 1) return result[0];
|
|
1032
|
+
return result;
|
|
950
1033
|
}
|
|
951
|
-
ArrayAdapter.prototype.immutable = false;
|
|
952
|
-
ArrayAdapter.prototype.sealed = false;
|
|
953
|
-
ArrayAdapter.prototype.keyField = null;
|
|
954
|
-
ArrayAdapter.prototype.cacheByKeyField = true;
|
|
955
|
-
ArrayAdapter.prototype.isTreeAdapter = false;
|
|
956
|
-
ArrayAdapter.autoInit = true;
|
|
957
1034
|
|
|
958
|
-
class
|
|
959
|
-
|
|
960
|
-
|
|
1035
|
+
class StaticText extends Widget {
|
|
1036
|
+
render() {
|
|
1037
|
+
return this.text;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
Widget.alias("static-text", StaticText);
|
|
961
1041
|
|
|
962
|
-
class
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1042
|
+
class Text extends Widget {
|
|
1043
|
+
constructor(config) {
|
|
1044
|
+
super(config);
|
|
1045
|
+
}
|
|
1046
|
+
init() {
|
|
1047
|
+
if (!this.value && (this.tpl || this.expr || this.bind))
|
|
1048
|
+
this.value = {
|
|
1049
|
+
tpl: this.tpl,
|
|
1050
|
+
expr: this.expr,
|
|
1051
|
+
bind: this.bind,
|
|
1052
|
+
};
|
|
1053
|
+
super.init();
|
|
1054
|
+
}
|
|
966
1055
|
declareData(...args) {
|
|
967
1056
|
super.declareData(
|
|
968
1057
|
{
|
|
969
|
-
|
|
970
|
-
sorters: undefined,
|
|
971
|
-
sortField: undefined,
|
|
972
|
-
sortDirection: undefined,
|
|
973
|
-
filterParams: {
|
|
974
|
-
structured: true,
|
|
975
|
-
},
|
|
1058
|
+
value: undefined,
|
|
976
1059
|
},
|
|
977
1060
|
...args,
|
|
978
1061
|
);
|
|
979
1062
|
}
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1063
|
+
render(context, { data }, key) {
|
|
1064
|
+
return data.value != null ? data.value : "";
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
Widget.alias("text", Text);
|
|
1068
|
+
|
|
1069
|
+
function exploreChildren(context, instance, children, previousResult, key, store) {
|
|
1070
|
+
let newChildren = previousResult || [];
|
|
1071
|
+
let oldChildren = previousResult || newChildren;
|
|
1072
|
+
let identical = previousResult ? 0 : -1;
|
|
1073
|
+
for (let c = 0; c < children.length; c++) {
|
|
1074
|
+
let cell = instance.getChild(context, children[c], key, store);
|
|
1075
|
+
if (cell.checkVisible(context)) {
|
|
1076
|
+
if (identical >= 0) {
|
|
1077
|
+
if (cell == oldChildren[identical]) identical++;
|
|
1078
|
+
else {
|
|
1079
|
+
newChildren = newChildren.slice(0, identical);
|
|
1080
|
+
identical = -1;
|
|
1081
|
+
newChildren.push(cell);
|
|
1082
|
+
}
|
|
1083
|
+
} else newChildren.push(cell);
|
|
1084
|
+
context.exploreStack.push(cell);
|
|
1085
|
+
if (cell.needsExploreCleanup) context.exploreStack.push(cell);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (identical >= 0 && identical != newChildren.length) newChildren = newChildren.slice(0, identical);
|
|
1089
|
+
return newChildren;
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// Base class for extending with custom Config types
|
|
1093
|
+
class ContainerBase extends Widget {
|
|
1094
|
+
init(context) {
|
|
1095
|
+
if (typeof this.ws !== "undefined") this.preserveWhitespace = this.ws;
|
|
1096
|
+
if (this.preserveWhitespace) this.trimWhitespace = false;
|
|
1097
|
+
let items = this.items || this.children || [];
|
|
998
1098
|
delete this.children;
|
|
999
1099
|
this.items = [];
|
|
1100
|
+
if (this.layout) {
|
|
1101
|
+
let layout = Container.create(this.layout, {
|
|
1102
|
+
items,
|
|
1103
|
+
});
|
|
1104
|
+
layout.init(context);
|
|
1105
|
+
this.layout = null;
|
|
1106
|
+
if ("noLayout" in layout && layout.noLayout) {
|
|
1107
|
+
this.useParentLayout = true;
|
|
1108
|
+
this.add(items);
|
|
1109
|
+
} else {
|
|
1110
|
+
this.add(layout);
|
|
1111
|
+
this.layout = layout;
|
|
1112
|
+
}
|
|
1113
|
+
} else {
|
|
1114
|
+
this.add(items);
|
|
1115
|
+
}
|
|
1000
1116
|
super.init();
|
|
1001
1117
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1118
|
+
exploreItems(context, instance, items) {
|
|
1119
|
+
instance.children = exploreChildren(context, instance, items, instance.cached.children, null, instance.store);
|
|
1120
|
+
if (instance.cache("children", instance.children)) instance.markShouldUpdate(context);
|
|
1004
1121
|
}
|
|
1005
|
-
|
|
1006
|
-
super.
|
|
1007
|
-
|
|
1008
|
-
if (instance.cached) delete instance.cached.rawData;
|
|
1122
|
+
explore(context, instance) {
|
|
1123
|
+
super.explore(context, instance);
|
|
1124
|
+
this.exploreItems(context, instance, this.items);
|
|
1009
1125
|
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
if (data.sortField)
|
|
1013
|
-
data.sorters = [
|
|
1014
|
-
{
|
|
1015
|
-
field: data.sortField,
|
|
1016
|
-
direction: data.sortDirection || "ASC",
|
|
1017
|
-
},
|
|
1018
|
-
];
|
|
1019
|
-
this.dataAdapter.sort(data.sorters);
|
|
1020
|
-
let filter = null;
|
|
1021
|
-
if (this.onCreateFilter) filter = instance.invoke("onCreateFilter", data.filterParams, instance);
|
|
1022
|
-
else if (this.filter) filter = (item) => this.filter(item, data.filterParams);
|
|
1023
|
-
this.dataAdapter.setFilter(filter);
|
|
1024
|
-
instance.mappedRecords = this.dataAdapter.getRecords(context, instance, data.records, instance.store);
|
|
1025
|
-
if (this.onTrackMappedRecords) {
|
|
1026
|
-
instance.invoke("onTrackMappedRecords", instance.mappedRecords, instance);
|
|
1027
|
-
}
|
|
1028
|
-
super.prepareData(context, instance);
|
|
1126
|
+
render(context, instance, key) {
|
|
1127
|
+
return this.renderChildren(context, instance, key);
|
|
1029
1128
|
}
|
|
1030
|
-
|
|
1031
|
-
let
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1129
|
+
renderChildren(_context, instance, key) {
|
|
1130
|
+
let preserveComplexContent = this.useParentLayout;
|
|
1131
|
+
function append(result, r) {
|
|
1132
|
+
if (r == null) return;
|
|
1133
|
+
//react element
|
|
1134
|
+
if (!r.hasOwnProperty("content")) {
|
|
1135
|
+
contentAppend(result, r);
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
if (r.useParentLayout) return r.content.forEach((x) => append(result, x));
|
|
1139
|
+
if (r.atomic || preserveComplexContent) {
|
|
1140
|
+
result.push(r);
|
|
1141
|
+
} else {
|
|
1142
|
+
let first = true;
|
|
1143
|
+
for (let k in r) if (contentAppend(result, r[k], !first)) first = false;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
let result = [];
|
|
1147
|
+
for (let i = 0; i < instance.children.length; i++) {
|
|
1148
|
+
append(result, instance.children[i].vdom);
|
|
1149
|
+
}
|
|
1150
|
+
if (this.useParentLayout)
|
|
1151
|
+
return {
|
|
1152
|
+
useParentLayout: true,
|
|
1153
|
+
content: result,
|
|
1154
|
+
};
|
|
1155
|
+
return result;
|
|
1042
1156
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
Repeater.prototype.cached = false;
|
|
1047
|
-
Repeater.prototype.immutable = false;
|
|
1048
|
-
Repeater.prototype.sealed = false;
|
|
1049
|
-
Repeater.prototype.isPureContainer = true;
|
|
1050
|
-
Widget.alias("repeater", Repeater);
|
|
1051
|
-
|
|
1052
|
-
class StructuredInstanceDataAccessor {
|
|
1053
|
-
instance;
|
|
1054
|
-
dataConfig;
|
|
1055
|
-
useParentStore;
|
|
1056
|
-
dataSelector;
|
|
1057
|
-
constructor(config) {
|
|
1058
|
-
this.instance = config.instance;
|
|
1059
|
-
this.dataConfig = config.data;
|
|
1060
|
-
this.useParentStore = config.useParentStore;
|
|
1061
|
-
this.dataSelector = getSelector(config.data);
|
|
1062
|
-
if (this.dataSelector.memoize) this.dataSelector = this.dataSelector.memoize();
|
|
1157
|
+
clear() {
|
|
1158
|
+
if (this.layout) this.layout.clear();
|
|
1159
|
+
else this.items = [];
|
|
1063
1160
|
}
|
|
1064
|
-
|
|
1065
|
-
return this.
|
|
1161
|
+
add(...args) {
|
|
1162
|
+
if (this.layout) return this.layout.add(...args);
|
|
1163
|
+
for (let a of args) {
|
|
1164
|
+
if (!a) continue;
|
|
1165
|
+
if (isArray(a)) {
|
|
1166
|
+
for (let c of a) this.add(c);
|
|
1167
|
+
} else if (isString(a)) {
|
|
1168
|
+
if (this.trimWhitespace) a = innerTextTrim(a);
|
|
1169
|
+
if (a) this.addText(a);
|
|
1170
|
+
} else if (a.isComponent) this.items.push(this.wrapItem(a));
|
|
1171
|
+
else {
|
|
1172
|
+
this.add(Widget.create(a, this.itemDefaults, {}));
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1066
1175
|
}
|
|
1067
|
-
|
|
1068
|
-
return
|
|
1176
|
+
wrapItem(item) {
|
|
1177
|
+
return item;
|
|
1069
1178
|
}
|
|
1070
|
-
|
|
1071
|
-
|
|
1179
|
+
addText(text) {
|
|
1180
|
+
if (this.plainText || text.indexOf("{") == -1 || text.indexOf("}") == -1)
|
|
1181
|
+
this.add(
|
|
1182
|
+
Widget.create(
|
|
1183
|
+
StaticText,
|
|
1184
|
+
{
|
|
1185
|
+
text: text,
|
|
1186
|
+
},
|
|
1187
|
+
{},
|
|
1188
|
+
),
|
|
1189
|
+
);
|
|
1190
|
+
else
|
|
1191
|
+
this.add(
|
|
1192
|
+
Widget.create(
|
|
1193
|
+
Text,
|
|
1194
|
+
{
|
|
1195
|
+
text: {
|
|
1196
|
+
tpl: text,
|
|
1197
|
+
},
|
|
1198
|
+
},
|
|
1199
|
+
{},
|
|
1200
|
+
),
|
|
1201
|
+
);
|
|
1072
1202
|
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1203
|
+
find(filter, options) {
|
|
1204
|
+
if (!options) options = {};
|
|
1205
|
+
if (!filter || !this.items) return [];
|
|
1206
|
+
let alias = filter;
|
|
1207
|
+
if (isString(filter)) filter = (w) => w.componentAlias == alias;
|
|
1208
|
+
if (filter.isComponentType) filter = (w) => w instanceof alias;
|
|
1209
|
+
let results = [];
|
|
1210
|
+
for (let i = 0; i < this.items.length; i++) {
|
|
1211
|
+
let w = this.items[i];
|
|
1212
|
+
if (w && !w.initialized) w.init();
|
|
1213
|
+
if (filter(w)) {
|
|
1214
|
+
results.push(w);
|
|
1215
|
+
if (options.first) break;
|
|
1216
|
+
}
|
|
1217
|
+
if (w && w.find) results.push(...w.find(filter, options));
|
|
1218
|
+
}
|
|
1219
|
+
return results;
|
|
1075
1220
|
}
|
|
1076
|
-
|
|
1077
|
-
return
|
|
1221
|
+
findFirst(filter, options) {
|
|
1222
|
+
return this.find(filter, {
|
|
1223
|
+
...options,
|
|
1224
|
+
first: true,
|
|
1225
|
+
})[0];
|
|
1078
1226
|
}
|
|
1079
1227
|
}
|
|
1228
|
+
ContainerBase.prototype.trimWhitespace = true;
|
|
1229
|
+
ContainerBase.prototype.plainText = true;
|
|
1230
|
+
ContainerBase.prototype.styled = false;
|
|
1231
|
+
// Closed type for direct usage - preserves ControllerProp ThisType
|
|
1232
|
+
class Container extends ContainerBase {}
|
|
1233
|
+
// Base class for styled containers with custom Config types
|
|
1234
|
+
class StyledContainerBase extends ContainerBase {}
|
|
1235
|
+
StyledContainerBase.prototype.styled = true;
|
|
1236
|
+
// Closed type for direct usage
|
|
1237
|
+
class StyledContainer extends StyledContainerBase {}
|
|
1080
1238
|
|
|
1081
|
-
class
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
rootName: this.rootName,
|
|
1092
|
-
nestedData: isObject(this.data)
|
|
1093
|
-
? new StructuredInstanceDataAccessor({
|
|
1094
|
-
instance,
|
|
1095
|
-
data: this.data,
|
|
1096
|
-
useParentStore: true,
|
|
1097
|
-
})
|
|
1098
|
-
: undefined,
|
|
1099
|
-
});
|
|
1100
|
-
super.initInstance(context, instance);
|
|
1239
|
+
// Base class for extending with custom Config types
|
|
1240
|
+
class PureContainerBase extends ContainerBase {}
|
|
1241
|
+
PureContainerBase.prototype.isPureContainer = true;
|
|
1242
|
+
// Closed type for direct usage - preserves ControllerProp ThisType
|
|
1243
|
+
class PureContainer extends PureContainerBase {}
|
|
1244
|
+
PureContainer.alias("pure-container", PureContainer);
|
|
1245
|
+
|
|
1246
|
+
class DataAdapter extends Component {
|
|
1247
|
+
constructor(config) {
|
|
1248
|
+
super(config);
|
|
1101
1249
|
}
|
|
1102
|
-
|
|
1103
|
-
|
|
1250
|
+
setFilter(filterFn) {
|
|
1251
|
+
this.filterFn = filterFn;
|
|
1104
1252
|
}
|
|
1253
|
+
sort(sorters) {}
|
|
1105
1254
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
let isBatching = 0;
|
|
1111
|
-
let promiseSubscribers = new SubscriberList();
|
|
1112
|
-
function batchUpdates(callback) {
|
|
1113
|
-
if (VDOM.DOM.unstable_batchedUpdates)
|
|
1114
|
-
VDOM.DOM.unstable_batchedUpdates(() => {
|
|
1115
|
-
isBatching++;
|
|
1116
|
-
try {
|
|
1117
|
-
callback();
|
|
1118
|
-
} finally {
|
|
1119
|
-
isBatching--;
|
|
1120
|
-
}
|
|
1121
|
-
});
|
|
1122
|
-
else callback();
|
|
1123
|
-
}
|
|
1124
|
-
function isBatchingUpdates() {
|
|
1125
|
-
return isBatching > 0;
|
|
1126
|
-
}
|
|
1127
|
-
function notifyBatchedUpdateStarting() {
|
|
1128
|
-
promiseSubscribers.execute((x) => {
|
|
1129
|
-
x.pending++;
|
|
1130
|
-
});
|
|
1131
|
-
}
|
|
1132
|
-
function notifyBatchedUpdateCompleted() {
|
|
1133
|
-
promiseSubscribers.execute((x) => {
|
|
1134
|
-
let cb = x;
|
|
1135
|
-
cb.finished++;
|
|
1136
|
-
if (cb.finished >= cb.pending) cb.complete(true);
|
|
1137
|
-
});
|
|
1138
|
-
}
|
|
1139
|
-
function batchUpdatesAndNotify(callback, notifyCallback, timeout = 1000) {
|
|
1140
|
-
let done = false;
|
|
1141
|
-
let timer;
|
|
1142
|
-
let unsubscribe;
|
|
1143
|
-
const update = {
|
|
1144
|
-
pending: 0,
|
|
1145
|
-
finished: 0,
|
|
1146
|
-
complete: (success) => {
|
|
1147
|
-
if (!done) {
|
|
1148
|
-
done = true;
|
|
1149
|
-
if (timer) clearInterval(timer);
|
|
1150
|
-
if (unsubscribe) unsubscribe();
|
|
1151
|
-
notifyCallback(!!success);
|
|
1152
|
-
}
|
|
1153
|
-
},
|
|
1154
|
-
};
|
|
1155
|
-
unsubscribe = promiseSubscribers.subscribe(update);
|
|
1156
|
-
batchUpdates(callback);
|
|
1157
|
-
if (update.pending <= update.finished) update.complete(true);
|
|
1158
|
-
else timer = setTimeout(update.complete, timeout);
|
|
1159
|
-
}
|
|
1255
|
+
DataAdapter.prototype.recordName = "$record";
|
|
1256
|
+
DataAdapter.prototype.indexName = "$index";
|
|
1257
|
+
DataAdapter.prototype.immutable = false;
|
|
1160
1258
|
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
static subscribe(callback) {
|
|
1173
|
-
let unsubscribe = subscribers$3.subscribe(callback);
|
|
1174
|
-
checkTimer();
|
|
1175
|
-
return unsubscribe;
|
|
1259
|
+
let contents = {};
|
|
1260
|
+
let localizations = {};
|
|
1261
|
+
let overrides = {};
|
|
1262
|
+
let defaults = {};
|
|
1263
|
+
let trackDefaults = false;
|
|
1264
|
+
class Localization {
|
|
1265
|
+
static register(key) {
|
|
1266
|
+
return (type) => {
|
|
1267
|
+
this.registerPrototype(key, type);
|
|
1268
|
+
return type;
|
|
1269
|
+
};
|
|
1176
1270
|
}
|
|
1177
|
-
static
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
if (!active) active = isSelfOrDescendant(el, getActiveElement());
|
|
1181
|
-
else if (!isSelfOrDescendant(el, focusedEl)) {
|
|
1182
|
-
active = false;
|
|
1183
|
-
callback(focusedEl);
|
|
1184
|
-
}
|
|
1185
|
-
});
|
|
1271
|
+
static registerPrototype(key, type) {
|
|
1272
|
+
contents[key] = type.prototype;
|
|
1273
|
+
if (overrides[key]) this.override(key, overrides[key]);
|
|
1186
1274
|
}
|
|
1187
|
-
static
|
|
1188
|
-
|
|
1189
|
-
let off = this.subscribe((focusedEl) => {
|
|
1190
|
-
if (!isSelfOrDescendant(el, focusedEl)) {
|
|
1191
|
-
callback(focusedEl);
|
|
1192
|
-
off();
|
|
1193
|
-
}
|
|
1194
|
-
});
|
|
1195
|
-
return off;
|
|
1275
|
+
static trackDefaults() {
|
|
1276
|
+
trackDefaults = true;
|
|
1196
1277
|
}
|
|
1197
|
-
static
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
if (getActiveElement() !== lastActiveElement) {
|
|
1204
|
-
lastActiveElement = getActiveElement();
|
|
1205
|
-
batchUpdates(() => {
|
|
1206
|
-
subscribers$3.notify(lastActiveElement);
|
|
1207
|
-
});
|
|
1208
|
-
checkTimer();
|
|
1209
|
-
}
|
|
1210
|
-
}, 0);
|
|
1211
|
-
}
|
|
1278
|
+
static restoreDefaults() {
|
|
1279
|
+
for (let type in defaults) {
|
|
1280
|
+
let proto = contents[type];
|
|
1281
|
+
if (!proto) continue;
|
|
1282
|
+
let d = defaults[type];
|
|
1283
|
+
for (let key in d) proto[key] = d[key];
|
|
1212
1284
|
}
|
|
1285
|
+
defaults = {};
|
|
1213
1286
|
}
|
|
1214
|
-
static
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
return focusable;
|
|
1222
|
-
}
|
|
1223
|
-
static focusFirstChild(el) {
|
|
1224
|
-
let focusable = findFirstChild(el, isFocusable);
|
|
1225
|
-
if (focusable) this.focus(focusable);
|
|
1226
|
-
return focusable;
|
|
1227
|
-
}
|
|
1228
|
-
static focusNext(el) {
|
|
1229
|
-
let next = el,
|
|
1230
|
-
skip = true;
|
|
1231
|
-
do {
|
|
1232
|
-
if (!skip) {
|
|
1233
|
-
let focusable = this.focusFirst(next);
|
|
1234
|
-
if (focusable) return focusable;
|
|
1235
|
-
}
|
|
1236
|
-
if (next.nextSibling) {
|
|
1237
|
-
next = next.nextSibling;
|
|
1238
|
-
skip = false;
|
|
1239
|
-
} else {
|
|
1240
|
-
next = next.parentNode;
|
|
1241
|
-
skip = true;
|
|
1287
|
+
static override(key, values) {
|
|
1288
|
+
overrides[key] = values;
|
|
1289
|
+
let p = contents[key];
|
|
1290
|
+
if (p) {
|
|
1291
|
+
if (trackDefaults && !defaults[key]) {
|
|
1292
|
+
let d = (defaults[key] = {});
|
|
1293
|
+
for (let key in values) d[key] = p[key];
|
|
1242
1294
|
}
|
|
1243
|
-
|
|
1295
|
+
Object.assign(p, values);
|
|
1296
|
+
}
|
|
1244
1297
|
}
|
|
1245
|
-
static
|
|
1246
|
-
|
|
1247
|
-
|
|
1298
|
+
static localize(culture, key, values) {
|
|
1299
|
+
let l = localizations[culture];
|
|
1300
|
+
if (!l) l = localizations[culture] = {};
|
|
1301
|
+
l[key] = {
|
|
1302
|
+
...l[key],
|
|
1303
|
+
...values,
|
|
1304
|
+
};
|
|
1248
1305
|
}
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1257
|
-
function offFocusOut(component) {
|
|
1258
|
-
if (component.oneFocusOut) {
|
|
1259
|
-
component.oneFocusOut();
|
|
1260
|
-
delete component.oneFocusOut;
|
|
1306
|
+
static setCulture(culture) {
|
|
1307
|
+
var l = localizations[culture];
|
|
1308
|
+
if (l) {
|
|
1309
|
+
for (var key in l) {
|
|
1310
|
+
var content = contents[key];
|
|
1311
|
+
if (content) Object.assign(content, l[key]);
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1261
1314
|
}
|
|
1262
1315
|
}
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1316
|
+
|
|
1317
|
+
// @ts-expect-error
|
|
1318
|
+
let stack = [
|
|
1319
|
+
{
|
|
1320
|
+
culture: "en",
|
|
1321
|
+
numberCulture: null,
|
|
1322
|
+
dateTimeCulture: null,
|
|
1323
|
+
cache: {},
|
|
1324
|
+
defaultCurrency: "USD",
|
|
1325
|
+
dateEncoding: (date) => date.toISOString(),
|
|
1326
|
+
timezone: null,
|
|
1327
|
+
},
|
|
1328
|
+
];
|
|
1329
|
+
function getDefaultCulture() {
|
|
1330
|
+
return stack[0];
|
|
1269
1331
|
}
|
|
1270
|
-
function
|
|
1271
|
-
|
|
1272
|
-
if (shouldRun && !timerId)
|
|
1273
|
-
timerId = setInterval(() => {
|
|
1274
|
-
FocusManager.nudge();
|
|
1275
|
-
}, timerInterval);
|
|
1276
|
-
if (!shouldRun && timerId) {
|
|
1277
|
-
clearInterval(timerId);
|
|
1278
|
-
timerId = null;
|
|
1279
|
-
}
|
|
1332
|
+
function getCurrentCulture() {
|
|
1333
|
+
return stack[stack.length - 1];
|
|
1280
1334
|
}
|
|
1281
|
-
function
|
|
1282
|
-
|
|
1335
|
+
function getCurrentCultureCache() {
|
|
1336
|
+
return getCurrentCulture().cache;
|
|
1283
1337
|
}
|
|
1284
|
-
function
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1338
|
+
function pushCulture(cultureInfo) {
|
|
1339
|
+
stack.push(cultureInfo);
|
|
1340
|
+
}
|
|
1341
|
+
function createCulture(cultureSpecs) {
|
|
1342
|
+
let current = getCurrentCulture();
|
|
1343
|
+
let info = {
|
|
1344
|
+
culture: current.culture,
|
|
1345
|
+
dateEncoding: current.dateEncoding,
|
|
1346
|
+
defaultCurrency: current.defaultCurrency,
|
|
1347
|
+
cache: {},
|
|
1348
|
+
};
|
|
1349
|
+
for (let key in cultureSpecs) {
|
|
1350
|
+
if (!cultureSpecs[key]) continue;
|
|
1351
|
+
info[key] = cultureSpecs[key];
|
|
1290
1352
|
}
|
|
1291
|
-
|
|
1292
|
-
let focusableParent = closestParent(
|
|
1293
|
-
target,
|
|
1294
|
-
(el) => isFocusable(el) && (!unfocusParentOverlay || !!el.dataset?.focusableOverlayContainer),
|
|
1295
|
-
);
|
|
1296
|
-
if (focusableParent && focusableParent !== document.body)
|
|
1297
|
-
focusableParent.focus({
|
|
1298
|
-
preventScroll: true,
|
|
1299
|
-
});
|
|
1300
|
-
else activeElement.blur();
|
|
1301
|
-
FocusManager.nudge();
|
|
1353
|
+
return info;
|
|
1302
1354
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
return subscribers$2.subscribe(callback);
|
|
1355
|
+
function popCulture(cultureSpecs) {
|
|
1356
|
+
if (stack.length == 1) throw new Error("Cannot pop the last culture object.");
|
|
1357
|
+
if (cultureSpecs && stack[stack.length - 1] !== cultureSpecs) {
|
|
1358
|
+
Console.warn("Popped culture object does not match the current one.");
|
|
1308
1359
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1360
|
+
return stack.pop();
|
|
1361
|
+
}
|
|
1362
|
+
class Culture {
|
|
1363
|
+
static setCulture(cultureCode) {
|
|
1364
|
+
let cultureSpecs = getDefaultCulture();
|
|
1365
|
+
cultureSpecs.culture = cultureCode;
|
|
1366
|
+
cultureSpecs.cache = {};
|
|
1367
|
+
Localization.setCulture(cultureCode);
|
|
1368
|
+
this.invalidateCache();
|
|
1313
1369
|
}
|
|
1314
|
-
static
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
obs.disconnect();
|
|
1320
|
-
};
|
|
1370
|
+
static setNumberCulture(cultureCode) {
|
|
1371
|
+
let cultureSpecs = getDefaultCulture();
|
|
1372
|
+
cultureSpecs.numberCulture = cultureCode;
|
|
1373
|
+
delete cultureSpecs.cache.numberCulture;
|
|
1374
|
+
this.invalidateCache();
|
|
1321
1375
|
}
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
static next() {
|
|
1328
|
-
return ++lastZIndex;
|
|
1376
|
+
static setDateTimeCulture(cultureCode) {
|
|
1377
|
+
let cultureSpecs = getDefaultCulture();
|
|
1378
|
+
cultureSpecs.dateTimeCulture = cultureCode;
|
|
1379
|
+
delete cultureSpecs.cache.dateTimeCulture;
|
|
1380
|
+
this.invalidateCache();
|
|
1329
1381
|
}
|
|
1330
|
-
static
|
|
1331
|
-
|
|
1382
|
+
static setDefaultCurrency(currencyCode) {
|
|
1383
|
+
let cultureSpecs = getDefaultCulture();
|
|
1384
|
+
cultureSpecs.defaultCurrency = currencyCode;
|
|
1385
|
+
this.invalidateCache();
|
|
1332
1386
|
}
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
function resolveNumberFormattingFlags(flags) {
|
|
1338
|
-
if (!flags) return null;
|
|
1339
|
-
let result = {};
|
|
1340
|
-
if (flags.indexOf("+") >= 0) result.signDisplay = "exceptZero";
|
|
1341
|
-
if (flags.indexOf("c") >= 0) result.notation = "compact";
|
|
1342
|
-
if (flags.indexOf("a") >= 0) result.currencySign = "accounting";
|
|
1343
|
-
return result;
|
|
1344
|
-
}
|
|
1345
|
-
function enableCultureSensitiveFormatting() {
|
|
1346
|
-
if (cultureSensitiveFormatsRegistered) return;
|
|
1347
|
-
cultureSensitiveFormatsRegistered = true;
|
|
1348
|
-
Format$1.registerFactory(["number", "n"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1349
|
-
let culture = Culture.getNumberCulture();
|
|
1350
|
-
let formatter = culture.getFormatter({
|
|
1351
|
-
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1352
|
-
...resolveNumberFormattingFlags(flags),
|
|
1353
|
-
});
|
|
1354
|
-
return (value) => formatter.format(value);
|
|
1355
|
-
});
|
|
1356
|
-
Format$1.registerFactory("currency", (format, currency, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1357
|
-
let culture = Culture.getNumberCulture();
|
|
1358
|
-
currency = currency || Culture.defaultCurrency;
|
|
1359
|
-
let formatter = culture.getFormatter({
|
|
1360
|
-
style: "currency",
|
|
1361
|
-
currency: currency,
|
|
1362
|
-
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1363
|
-
...resolveNumberFormattingFlags(flags),
|
|
1364
|
-
});
|
|
1365
|
-
return (value) => formatter.format(value);
|
|
1366
|
-
});
|
|
1367
|
-
Format$1.registerFactory(["percentage", "p", "%"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1368
|
-
let culture = Culture.getNumberCulture();
|
|
1369
|
-
let formatter = culture.getFormatter({
|
|
1370
|
-
style: "percent",
|
|
1371
|
-
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1372
|
-
...resolveNumberFormattingFlags(flags),
|
|
1373
|
-
});
|
|
1374
|
-
return (value) => formatter.format(value);
|
|
1375
|
-
});
|
|
1376
|
-
Format$1.registerFactory(["percentSign", "ps"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1377
|
-
let culture = Culture.getNumberCulture();
|
|
1378
|
-
let formatter = culture.getFormatter({
|
|
1379
|
-
style: "percent",
|
|
1380
|
-
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1381
|
-
...resolveNumberFormattingFlags(flags),
|
|
1382
|
-
});
|
|
1383
|
-
return (value) => formatter.format(value / 100);
|
|
1384
|
-
});
|
|
1385
|
-
Format$1.registerFactory(["date", "d"], (fmt, format = "yyyyMMdd") => {
|
|
1386
|
-
let culture = Culture.getDateTimeCulture();
|
|
1387
|
-
let formatter = culture.getFormatter(format);
|
|
1388
|
-
return (value) => formatter.format(parseDateInvariant(value));
|
|
1389
|
-
});
|
|
1390
|
-
Format$1.registerFactory(["time", "t"], (fmt, format = "hhmmss") => {
|
|
1391
|
-
let culture = Culture.getDateTimeCulture();
|
|
1392
|
-
let formatter = culture.getFormatter(format);
|
|
1393
|
-
return (value) => formatter.format(parseDateInvariant(value));
|
|
1394
|
-
});
|
|
1395
|
-
Format$1.registerFactory(["datetime", "dt"], (fmt, format = "yyyyMd hhmm") => {
|
|
1396
|
-
let culture = Culture.getDateTimeCulture();
|
|
1397
|
-
let formatter = culture.getFormatter(format);
|
|
1398
|
-
return (value) => formatter.format(parseDateInvariant(value));
|
|
1399
|
-
});
|
|
1400
|
-
setGetFormatCacheCallback(() => {
|
|
1401
|
-
let cache = getCurrentCultureCache();
|
|
1402
|
-
if (!cache.formatCache) cache.formatCache = {};
|
|
1403
|
-
return cache.formatCache;
|
|
1404
|
-
});
|
|
1405
|
-
setGetExpressionCacheCallback(() => {
|
|
1406
|
-
let cache = getCurrentCultureCache();
|
|
1407
|
-
if (!cache.exprCache) cache.exprCache = {};
|
|
1408
|
-
return cache.exprCache;
|
|
1409
|
-
});
|
|
1410
|
-
setGetStringTemplateCacheCallback(() => {
|
|
1411
|
-
let cache = getCurrentCultureCache();
|
|
1412
|
-
if (!cache.strTplCache) cache.strTplCache = {};
|
|
1413
|
-
return cache.strTplCache;
|
|
1414
|
-
});
|
|
1415
|
-
GlobalCacheIdentifier.change();
|
|
1416
|
-
}
|
|
1417
|
-
|
|
1418
|
-
let instanceId = 1000;
|
|
1419
|
-
/**
|
|
1420
|
-
* Base Instance class
|
|
1421
|
-
*/
|
|
1422
|
-
class Instance {
|
|
1423
|
-
// Selectors
|
|
1424
|
-
dataSelector;
|
|
1425
|
-
// Lifecycle flags
|
|
1426
|
-
initialized;
|
|
1427
|
-
destroySubscriptions;
|
|
1428
|
-
helpers;
|
|
1429
|
-
components;
|
|
1430
|
-
constructor(widget, key, parent, parentStore) {
|
|
1431
|
-
this.widget = widget;
|
|
1432
|
-
this.key = key;
|
|
1433
|
-
this.id = String(++instanceId);
|
|
1434
|
-
this.cached = {};
|
|
1435
|
-
this.parent = parent;
|
|
1436
|
-
this.parentStore = parentStore ?? parent?.store;
|
|
1437
|
-
if (this.parentStore == null) throw new Error("Cannot create instance without a parent store.");
|
|
1387
|
+
static setDefaultTimezone(timezone) {
|
|
1388
|
+
let cultureSpecs = getDefaultCulture();
|
|
1389
|
+
cultureSpecs.timezone = timezone;
|
|
1390
|
+
this.invalidateCache();
|
|
1438
1391
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1392
|
+
static setDefaultDateEncoding(encoding) {
|
|
1393
|
+
let cultureSpecs = getDefaultCulture();
|
|
1394
|
+
cultureSpecs.dateEncoding = encoding;
|
|
1395
|
+
this.invalidateCache();
|
|
1442
1396
|
}
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
this.widget.initialized = true;
|
|
1448
|
-
}
|
|
1449
|
-
if (!this.dataSelector) {
|
|
1450
|
-
this.widget.selector.init(this.parentStore);
|
|
1451
|
-
this.dataSelector = this.widget.selector.createStoreSelector();
|
|
1452
|
-
}
|
|
1453
|
-
// init instance might change the store, so this must go before the controller initialization
|
|
1454
|
-
this.widget.initInstance(context, this);
|
|
1455
|
-
// initInstance can set the store, otherwise use parent store
|
|
1456
|
-
if (!this.store) this.store = this.parentStore;
|
|
1457
|
-
if (this.widget.onInit) this.widget.onInit(context, this);
|
|
1458
|
-
this.widget.initState(context, this);
|
|
1459
|
-
if (this.widget.controller)
|
|
1460
|
-
this.controller = Controller.create(this.widget.controller, {
|
|
1461
|
-
widget: this.widget,
|
|
1462
|
-
instance: this,
|
|
1463
|
-
store: this.store,
|
|
1464
|
-
});
|
|
1465
|
-
if (
|
|
1466
|
-
this.widget.exploreCleanup ||
|
|
1467
|
-
this.widget.outerLayout ||
|
|
1468
|
-
this.widget.isContent ||
|
|
1469
|
-
this.widget.controller ||
|
|
1470
|
-
this.widget.prepareCleanup
|
|
1471
|
-
)
|
|
1472
|
-
this.needsExploreCleanup = true;
|
|
1473
|
-
if (this.widget.prepare || this.widget.controller) this.needsPrepare = true;
|
|
1474
|
-
if (this.widget.cleanup || this.widget.controller) this.needsCleanup = true;
|
|
1475
|
-
this.initialized = true;
|
|
1397
|
+
static invalidateCache() {
|
|
1398
|
+
GlobalCacheIdentifier.change();
|
|
1399
|
+
invalidateExpressionCache();
|
|
1400
|
+
invalidateStringTemplateCache();
|
|
1476
1401
|
}
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
const wasVisible = this.visible;
|
|
1480
|
-
this.rawData = this.dataSelector(this.store);
|
|
1481
|
-
this.visible = this.widget.checkVisible(context, this, this.rawData);
|
|
1482
|
-
if (this.visible && !this.detached) this.parent.instanceCache.addChild(this);
|
|
1483
|
-
this.explored = false;
|
|
1484
|
-
this.prepared = false;
|
|
1485
|
-
if (!this.visible && wasVisible) this.destroy();
|
|
1486
|
-
return this.visible;
|
|
1402
|
+
static get defaultCurrency() {
|
|
1403
|
+
return getCurrentCulture().defaultCurrency;
|
|
1487
1404
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
context.exploreStack.push(this);
|
|
1491
|
-
if (this.needsExploreCleanup) context.exploreStack.push(this);
|
|
1492
|
-
return true;
|
|
1493
|
-
}
|
|
1494
|
-
return false;
|
|
1405
|
+
static get culture() {
|
|
1406
|
+
return getCurrentCulture().culture;
|
|
1495
1407
|
}
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
if (
|
|
1499
|
-
|
|
1500
|
-
this.cacheList[key] = value;
|
|
1501
|
-
return true;
|
|
1408
|
+
static getNumberCulture() {
|
|
1409
|
+
let { cache, numberCulture, culture } = getCurrentCulture();
|
|
1410
|
+
if (!cache.numberCulture) cache.numberCulture = new NumberCulture(numberCulture ?? culture);
|
|
1411
|
+
return cache.numberCulture;
|
|
1502
1412
|
}
|
|
1503
|
-
|
|
1504
|
-
let
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
renderList.reverse();
|
|
1511
|
-
renderList = ins.renderList;
|
|
1512
|
-
renderList.markReverseIndex();
|
|
1513
|
-
}
|
|
1514
|
-
ins.shouldUpdate = true;
|
|
1515
|
-
renderList.data.push(ins);
|
|
1516
|
-
ins = ins.widget.isContent
|
|
1517
|
-
? ins.contentPlaceholder
|
|
1518
|
-
: ins.parent?.outerLayout === ins
|
|
1519
|
-
? ins.parent?.parent
|
|
1520
|
-
: ins.parent;
|
|
1521
|
-
}
|
|
1522
|
-
renderList.reverse();
|
|
1413
|
+
static getDateTimeCulture() {
|
|
1414
|
+
let { cache, dateTimeCulture, culture, timezone } = getCurrentCulture();
|
|
1415
|
+
if (!cache.dateTimeCulture)
|
|
1416
|
+
cache.dateTimeCulture = new DateTimeCulture(dateTimeCulture ?? culture, {
|
|
1417
|
+
defaultTimezone: timezone,
|
|
1418
|
+
});
|
|
1419
|
+
return cache.dateTimeCulture;
|
|
1523
1420
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
if (this.explored) {
|
|
1527
|
-
if (this.widget.prepareCleanup) context.prepareList.push(this);
|
|
1528
|
-
if (this.widget.exploreCleanup) this.widget.exploreCleanup(context, this);
|
|
1529
|
-
if (this.parent?.outerLayout === this) context.popNamedValue("content", "body");
|
|
1530
|
-
if (this.widget.controller) context.pop("controller");
|
|
1531
|
-
return;
|
|
1532
|
-
}
|
|
1533
|
-
this.explored = true;
|
|
1534
|
-
if (this.needsPrepare) context.prepareList.push(this);
|
|
1535
|
-
else this.prepared = true;
|
|
1536
|
-
if (this.needsCleanup) context.cleanupList.push(this);
|
|
1537
|
-
if (this.instanceCache) this.instanceCache.mark();
|
|
1538
|
-
//controller may reconfigure the widget and need to go before shouldUpdate calculation
|
|
1539
|
-
this.parentOptions = context.parentOptions;
|
|
1540
|
-
if (!this.controller) {
|
|
1541
|
-
if (context.controller) this.controller = context.controller;
|
|
1542
|
-
else if (this.parent?.controller) this.controller = this.parent?.controller;
|
|
1543
|
-
}
|
|
1544
|
-
this.destroyTracked = false;
|
|
1545
|
-
if (this.controller) {
|
|
1546
|
-
if (this.widget.controller) {
|
|
1547
|
-
if (!this.controller.initialized) {
|
|
1548
|
-
this.controller.init(context);
|
|
1549
|
-
this.controller.initialized = true;
|
|
1550
|
-
}
|
|
1551
|
-
context.push("controller", this.controller);
|
|
1552
|
-
this.controller.explore(context);
|
|
1553
|
-
if (this.controller.onDestroy && this.controller.widget == this.widget) this.trackDestroy();
|
|
1554
|
-
}
|
|
1555
|
-
}
|
|
1556
|
-
if (this.widget.onDestroy || isNonEmptyArray(this.destroySubscriptions)) this.trackDestroy();
|
|
1557
|
-
this.renderList = this.assignedRenderList || this.parent?.renderList || context.getRootRenderList();
|
|
1558
|
-
let shouldUpdate =
|
|
1559
|
-
this.rawData !== this.cached.rawData ||
|
|
1560
|
-
this.state !== this.cached.state ||
|
|
1561
|
-
this.widget.version !== this.cached.widgetVersion ||
|
|
1562
|
-
this.cached.globalCacheIdentifier !== GlobalCacheIdentifier.get();
|
|
1563
|
-
if (shouldUpdate) {
|
|
1564
|
-
this.data = {
|
|
1565
|
-
...this.rawData,
|
|
1566
|
-
};
|
|
1567
|
-
this.widget.prepareData(context, this);
|
|
1568
|
-
debug(processDataFlag, this.widget);
|
|
1569
|
-
}
|
|
1570
|
-
//onExplore might set the outer layout
|
|
1571
|
-
if (this.widget.onExplore) this.widget.onExplore(context, this);
|
|
1572
|
-
if (this.parent?.outerLayout === this) {
|
|
1573
|
-
this.renderList = this.renderList.insertRight();
|
|
1574
|
-
context.pushNamedValue("content", "body", this.parent);
|
|
1575
|
-
}
|
|
1576
|
-
if (this.widget.outerLayout) {
|
|
1577
|
-
this.outerLayout = this.getChild(context, this.widget.outerLayout, null, this.store);
|
|
1578
|
-
this.outerLayout.scheduleExploreIfVisible(context);
|
|
1579
|
-
this.renderList = this.renderList.insertLeft();
|
|
1580
|
-
}
|
|
1581
|
-
if (this.widget.isContent) {
|
|
1582
|
-
this.contentPlaceholder = context.contentPlaceholder && context.contentPlaceholder[this.widget.putInto];
|
|
1583
|
-
if (this.contentPlaceholder) context.contentPlaceholder[this.widget.putInto](this);
|
|
1584
|
-
else {
|
|
1585
|
-
this.renderList = this.renderList.insertLeft();
|
|
1586
|
-
context.pushNamedValue("content", this.widget.putInto, this);
|
|
1587
|
-
if (!context.contentList) context.contentList = {};
|
|
1588
|
-
let list = context.contentList[this.widget.putInto];
|
|
1589
|
-
if (!list) list = context.contentList[this.widget.putInto] = [];
|
|
1590
|
-
list.push(this);
|
|
1591
|
-
}
|
|
1592
|
-
}
|
|
1593
|
-
this.shouldUpdate = false;
|
|
1594
|
-
if (shouldUpdate || this.childStateDirty || !this.widget.memoize) this.markShouldUpdate(context);
|
|
1595
|
-
context.exploreStack.hop();
|
|
1596
|
-
if (this.widget.helpers) {
|
|
1597
|
-
this.helpers = {};
|
|
1598
|
-
for (let cmp in this.widget.helpers) {
|
|
1599
|
-
let helper = this.widget.helpers[cmp];
|
|
1600
|
-
if (helper) {
|
|
1601
|
-
let ins = this.getChild(context, helper);
|
|
1602
|
-
if (ins.scheduleExploreIfVisible(context)) this.helpers[cmp] = ins;
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
}
|
|
1606
|
-
//TODO: check do we need to pass data here?
|
|
1607
|
-
this.widget.explore(context, this, this.data);
|
|
1421
|
+
static getDefaultDateEncoding() {
|
|
1422
|
+
return getCurrentCulture().dateEncoding;
|
|
1608
1423
|
}
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
if (
|
|
1612
|
-
|
|
1613
|
-
return;
|
|
1614
|
-
}
|
|
1615
|
-
this.prepared = true;
|
|
1616
|
-
if (this.widget.prepare) this.widget.prepare(context, this);
|
|
1617
|
-
if (this.widget.controller && this.controller?.prepare) this.controller.prepare(context);
|
|
1424
|
+
static getComparer(options) {
|
|
1425
|
+
let { culture } = getCurrentCulture();
|
|
1426
|
+
if (typeof Intl.Collator != "undefined") return new Intl.Collator(culture, options).compare;
|
|
1427
|
+
return defaultCompare;
|
|
1618
1428
|
}
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
if (this.widget.isContent || this.outerLayout) this.contentVDOM = vdom;
|
|
1625
|
-
else this.vdom = vdom;
|
|
1626
|
-
}
|
|
1627
|
-
if (this.cacheList) {
|
|
1628
|
-
for (const key in this.cacheList) {
|
|
1629
|
-
this.cached[key] = this.cacheList[key];
|
|
1630
|
-
}
|
|
1631
|
-
}
|
|
1632
|
-
this.cacheList = null;
|
|
1633
|
-
this.cached.rawData = this.rawData;
|
|
1634
|
-
this.cached.data = this.data;
|
|
1635
|
-
this.cached.state = this.state;
|
|
1636
|
-
this.cached.widgetVersion = this.widget.version;
|
|
1637
|
-
this.cached.globalCacheIdentifier = GlobalCacheIdentifier.get();
|
|
1638
|
-
this.childStateDirty = false;
|
|
1639
|
-
if (this.instanceCache) this.instanceCache.sweep();
|
|
1640
|
-
if (this.parent?.outerLayout === this) {
|
|
1641
|
-
//if outer layouts are chained we need to find the originating element (last element with OL set)
|
|
1642
|
-
let parent = this.parent;
|
|
1643
|
-
while (parent.parent?.outerLayout == parent) parent = parent.parent;
|
|
1644
|
-
parent.vdom = this.vdom;
|
|
1645
|
-
}
|
|
1646
|
-
return this.vdom;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
class ArrayAdapter extends DataAdapter {
|
|
1432
|
+
constructor(config) {
|
|
1433
|
+
super(config);
|
|
1647
1434
|
}
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1435
|
+
init() {
|
|
1436
|
+
this.recordsAccessor = this.recordsBinding ? getAccessor(this.recordsBinding) : getAccessor(this.recordsAccessor);
|
|
1437
|
+
this.recordName = this.recordName?.toString() || "$record";
|
|
1438
|
+
this.indexName = this.indexName?.toString() || "$index";
|
|
1651
1439
|
}
|
|
1652
|
-
|
|
1653
|
-
if (!
|
|
1654
|
-
|
|
1655
|
-
|
|
1440
|
+
initInstance(context, instance) {
|
|
1441
|
+
if (!instance.recordStoreCache) {
|
|
1442
|
+
instance.recordStoreCache = new WeakMap();
|
|
1443
|
+
instance.cacheByKey = {};
|
|
1444
|
+
}
|
|
1445
|
+
if (!instance.recordsAccessor && this.recordsAccessor) {
|
|
1446
|
+
instance.recordsAccessor = this.recordsAccessor.bindInstance
|
|
1447
|
+
? this.recordsAccessor.bindInstance(instance)
|
|
1448
|
+
: this.recordsAccessor;
|
|
1656
1449
|
}
|
|
1657
1450
|
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
if (!this.destroySubscriptions) this.destroySubscriptions = [];
|
|
1664
|
-
this.destroySubscriptions.push(callback);
|
|
1665
|
-
this.trackDestroy();
|
|
1666
|
-
return () => {
|
|
1667
|
-
if (this.destroySubscriptions) {
|
|
1668
|
-
this.destroySubscriptions = this.destroySubscriptions.filter((cb) => cb !== callback);
|
|
1669
|
-
}
|
|
1670
|
-
};
|
|
1451
|
+
getRecords(context, instance, records, parentStore) {
|
|
1452
|
+
if (!instance.recordStoreCache) {
|
|
1453
|
+
this.initInstance(context, instance);
|
|
1454
|
+
}
|
|
1455
|
+
return this.mapRecords(context, instance, records, parentStore, instance.recordsAccessor);
|
|
1671
1456
|
}
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
this.
|
|
1457
|
+
mapRecords(context, instance, records, parentStore, recordsAccessor) {
|
|
1458
|
+
let result = [];
|
|
1459
|
+
if (!instance.recordStoreCache) {
|
|
1460
|
+
this.initInstance(context, instance);
|
|
1676
1461
|
}
|
|
1677
|
-
if (
|
|
1678
|
-
|
|
1679
|
-
|
|
1462
|
+
if (isArray(records)) {
|
|
1463
|
+
records.forEach((data, index) => {
|
|
1464
|
+
if (this.filterFn && !this.filterFn(data)) return;
|
|
1465
|
+
const record = this.mapRecord(context, instance, data, parentStore, recordsAccessor, index);
|
|
1466
|
+
result.push(record);
|
|
1467
|
+
});
|
|
1680
1468
|
}
|
|
1681
|
-
if (this.
|
|
1682
|
-
|
|
1683
|
-
if (this.widget.onDestroy) this.widget.onDestroy(this);
|
|
1684
|
-
if (
|
|
1685
|
-
this.widget.controller &&
|
|
1686
|
-
this.controller &&
|
|
1687
|
-
this.controller.onDestroy &&
|
|
1688
|
-
this.controller.widget == this.widget
|
|
1689
|
-
)
|
|
1690
|
-
this.controller.onDestroy();
|
|
1691
|
-
this.destroyTracked = false;
|
|
1469
|
+
if (this.sorter && !this.preserveOrder) {
|
|
1470
|
+
result = this.sorter(result);
|
|
1692
1471
|
}
|
|
1472
|
+
return result;
|
|
1693
1473
|
}
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1474
|
+
mapRecord(context, instance, data, parentStore, recordsAccessor, index) {
|
|
1475
|
+
const key = this.cacheByKeyField && this.keyField && isObject(data) ? data[this.keyField] : null;
|
|
1476
|
+
let recordStore = key != null ? instance.cacheByKey[key] : instance.recordStoreCache.get(data);
|
|
1477
|
+
if (recordsAccessor) {
|
|
1478
|
+
if (!recordStore) {
|
|
1479
|
+
recordStore = new ArrayElementView({
|
|
1480
|
+
store: parentStore,
|
|
1481
|
+
arrayAccessor: recordsAccessor,
|
|
1482
|
+
itemIndex: index,
|
|
1483
|
+
recordAlias: this.recordName,
|
|
1484
|
+
indexAlias: this.indexName,
|
|
1485
|
+
immutable: this.immutable,
|
|
1486
|
+
sealed: this.sealed,
|
|
1487
|
+
});
|
|
1488
|
+
} else {
|
|
1489
|
+
recordStore.setStore(parentStore);
|
|
1490
|
+
recordStore.setIndex(index);
|
|
1491
|
+
}
|
|
1492
|
+
} else {
|
|
1493
|
+
if (!recordStore) {
|
|
1494
|
+
recordStore = new ReadOnlyDataView({
|
|
1495
|
+
store: parentStore,
|
|
1496
|
+
data: {
|
|
1497
|
+
[this.recordName]: data,
|
|
1498
|
+
[this.indexName]: index,
|
|
1499
|
+
},
|
|
1500
|
+
immutable: this.immutable,
|
|
1501
|
+
sealed: this.sealed,
|
|
1502
|
+
});
|
|
1503
|
+
} else {
|
|
1504
|
+
recordStore.setStore(parentStore);
|
|
1505
|
+
recordStore.setData({
|
|
1506
|
+
[this.recordName]: data,
|
|
1507
|
+
[this.indexName]: index,
|
|
1508
|
+
});
|
|
1702
1509
|
}
|
|
1703
1510
|
}
|
|
1704
|
-
if (
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
while (parent) {
|
|
1709
|
-
parent.childStateDirty = true;
|
|
1710
|
-
parent = parent.parent;
|
|
1511
|
+
if (key != null) {
|
|
1512
|
+
instance.cacheByKey[key] = recordStore;
|
|
1513
|
+
} else if (isObject(data)) {
|
|
1514
|
+
instance.recordStoreCache.set(data, recordStore);
|
|
1711
1515
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1516
|
+
return {
|
|
1517
|
+
store: recordStore,
|
|
1518
|
+
index: index,
|
|
1519
|
+
data: data,
|
|
1520
|
+
type: "data",
|
|
1521
|
+
key: this.keyField && isObject(data) ? data[this.keyField] : index,
|
|
1522
|
+
};
|
|
1715
1523
|
}
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1524
|
+
setFilter(filterFn) {
|
|
1525
|
+
this.filterFn = filterFn;
|
|
1526
|
+
}
|
|
1527
|
+
getComparer(sortOptions) {
|
|
1528
|
+
return sortOptions ? Culture.getComparer(sortOptions) : undefined;
|
|
1529
|
+
}
|
|
1530
|
+
buildSorter(sorters) {
|
|
1531
|
+
if (isArray(sorters) && sorters.length > 0) {
|
|
1532
|
+
let dataAccessor;
|
|
1533
|
+
let fieldValueMapper;
|
|
1534
|
+
if (sorters.every((x) => x.field && x.value == null)) {
|
|
1535
|
+
dataAccessor = (x) => x.data;
|
|
1536
|
+
fieldValueMapper = (x) => ({
|
|
1537
|
+
bind: x.field,
|
|
1538
|
+
});
|
|
1539
|
+
} else {
|
|
1540
|
+
dataAccessor = (x) => x.store.getData();
|
|
1541
|
+
fieldValueMapper = (x) => ({
|
|
1542
|
+
bind: this.recordName + "." + x.field,
|
|
1543
|
+
});
|
|
1544
|
+
}
|
|
1545
|
+
this.sorter = sorter(
|
|
1546
|
+
sorters.map((x) => {
|
|
1547
|
+
const s = Object.assign({}, x);
|
|
1548
|
+
if (s.field && s.value == null) {
|
|
1549
|
+
s.value = fieldValueMapper(s);
|
|
1550
|
+
}
|
|
1551
|
+
if (!s.comparer) {
|
|
1552
|
+
s.comparer = this.getComparer(isDefined(s.sortOptions) ? s.sortOptions : this.sortOptions);
|
|
1553
|
+
}
|
|
1554
|
+
return s;
|
|
1555
|
+
}),
|
|
1556
|
+
dataAccessor,
|
|
1557
|
+
);
|
|
1558
|
+
} else {
|
|
1559
|
+
this.sorter = undefined;
|
|
1721
1560
|
}
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
return true;
|
|
1561
|
+
}
|
|
1562
|
+
sort(sorters) {
|
|
1563
|
+
if (sorters) {
|
|
1564
|
+
this.buildSorter(sorters);
|
|
1727
1565
|
}
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
ArrayAdapter.prototype.immutable = false;
|
|
1569
|
+
ArrayAdapter.prototype.sealed = false;
|
|
1570
|
+
ArrayAdapter.prototype.keyField = null;
|
|
1571
|
+
ArrayAdapter.prototype.cacheByKeyField = true;
|
|
1572
|
+
ArrayAdapter.prototype.isTreeAdapter = false;
|
|
1573
|
+
ArrayAdapter.autoInit = true;
|
|
1574
|
+
|
|
1575
|
+
class UseParentLayout extends PureContainer {}
|
|
1576
|
+
UseParentLayout.prototype.noLayout = true;
|
|
1577
|
+
UseParentLayout.prototype.useParentLayout = true;
|
|
1578
|
+
|
|
1579
|
+
class Repeater extends ContainerBase {
|
|
1580
|
+
recordsAccessor;
|
|
1581
|
+
item;
|
|
1582
|
+
filter;
|
|
1583
|
+
declareData(...args) {
|
|
1584
|
+
super.declareData(
|
|
1585
|
+
{
|
|
1586
|
+
records: undefined,
|
|
1587
|
+
sorters: undefined,
|
|
1588
|
+
sortField: undefined,
|
|
1589
|
+
sortDirection: undefined,
|
|
1590
|
+
filterParams: {
|
|
1591
|
+
structured: true,
|
|
1592
|
+
},
|
|
1593
|
+
},
|
|
1594
|
+
...args,
|
|
1595
|
+
);
|
|
1596
|
+
}
|
|
1597
|
+
init() {
|
|
1598
|
+
this.recordsAccessor = getAccessor(this.records);
|
|
1599
|
+
if (this.recordAlias) this.recordName = this.recordAlias;
|
|
1600
|
+
if (this.indexAlias) this.indexName = this.indexAlias;
|
|
1601
|
+
this.dataAdapter = ArrayAdapter.create({
|
|
1602
|
+
...this.dataAdapter,
|
|
1603
|
+
recordName: this.recordName,
|
|
1604
|
+
indexName: this.indexName,
|
|
1605
|
+
keyField: this.keyField,
|
|
1606
|
+
immutable: this.immutable,
|
|
1607
|
+
sealed: this.sealed,
|
|
1608
|
+
recordsAccessor: this.recordsAccessor,
|
|
1609
|
+
sortOptions: this.sortOptions,
|
|
1610
|
+
});
|
|
1611
|
+
this.item = PureContainer.create({
|
|
1612
|
+
children: this.items || this.children,
|
|
1613
|
+
layout: UseParentLayout,
|
|
1614
|
+
});
|
|
1615
|
+
delete this.children;
|
|
1616
|
+
this.items = [];
|
|
1617
|
+
super.init();
|
|
1618
|
+
}
|
|
1619
|
+
initInstance(context, instance) {
|
|
1620
|
+
this.dataAdapter.initInstance(context, instance);
|
|
1621
|
+
}
|
|
1622
|
+
applyParentStore(instance) {
|
|
1623
|
+
super.applyParentStore(instance);
|
|
1624
|
+
// force prepareData to execute again and propagate the store change to the records
|
|
1625
|
+
if (instance.cached) delete instance.cached.rawData;
|
|
1626
|
+
}
|
|
1627
|
+
prepareData(context, instance) {
|
|
1628
|
+
let { data } = instance;
|
|
1629
|
+
if (data.sortField)
|
|
1630
|
+
data.sorters = [
|
|
1631
|
+
{
|
|
1632
|
+
field: data.sortField,
|
|
1633
|
+
direction: data.sortDirection || "ASC",
|
|
1634
|
+
},
|
|
1635
|
+
];
|
|
1636
|
+
this.dataAdapter.sort(data.sorters);
|
|
1637
|
+
let filter = null;
|
|
1638
|
+
if (this.onCreateFilter) filter = instance.invoke("onCreateFilter", data.filterParams, instance);
|
|
1639
|
+
else if (this.filter) filter = (item) => this.filter(item, data.filterParams);
|
|
1640
|
+
this.dataAdapter.setFilter(filter);
|
|
1641
|
+
instance.mappedRecords = this.dataAdapter.getRecords(context, instance, data.records, instance.store);
|
|
1642
|
+
if (this.onTrackMappedRecords) {
|
|
1643
|
+
instance.invoke("onTrackMappedRecords", instance.mappedRecords, instance);
|
|
1750
1644
|
}
|
|
1751
|
-
|
|
1752
|
-
}
|
|
1753
|
-
definePropertySetter(prop, setter) {
|
|
1754
|
-
if (!this.setters) this.setters = {};
|
|
1755
|
-
this.setters[prop] = setter;
|
|
1645
|
+
super.prepareData(context, instance);
|
|
1756
1646
|
}
|
|
1757
|
-
|
|
1758
|
-
let
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
} else if (isString(pObj.set)) {
|
|
1768
|
-
this.controller?.[pObj.set](value, this);
|
|
1769
|
-
changed = true;
|
|
1770
|
-
}
|
|
1771
|
-
} else if (pObj.action) {
|
|
1772
|
-
const action = pObj.action(value, this);
|
|
1773
|
-
this.store.dispatch(action);
|
|
1774
|
-
changed = true;
|
|
1775
|
-
} else if (isString(pObj.bind) || isAccessorChain(pObj.bind)) {
|
|
1776
|
-
changed = this.store.set(pObj.bind, value);
|
|
1777
|
-
}
|
|
1778
|
-
} else if (isAccessorChain(p)) {
|
|
1779
|
-
changed = this.store.set(p.toString(), value);
|
|
1780
|
-
}
|
|
1647
|
+
explore(context, instance, data) {
|
|
1648
|
+
let instances = [];
|
|
1649
|
+
instance.mappedRecords.forEach((record) => {
|
|
1650
|
+
let subInstance = instance.getChild(context, this.item, record.key, record.store);
|
|
1651
|
+
let changed = subInstance.cache("recordData", record.data) || subInstance.cache("key", record.key);
|
|
1652
|
+
subInstance.record = record;
|
|
1653
|
+
if (this.cached && !changed && subInstance.visible && !subInstance.childStateDirty) {
|
|
1654
|
+
instances.push(subInstance);
|
|
1655
|
+
subInstance.shouldUpdate = false;
|
|
1656
|
+
} else if (subInstance.scheduleExploreIfVisible(context)) instances.push(subInstance);
|
|
1781
1657
|
});
|
|
1782
|
-
|
|
1658
|
+
instance.children = instances;
|
|
1783
1659
|
}
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
else
|
|
1805
|
-
throw new Error(
|
|
1806
|
-
`Cannot change nested data value for ${key} the defined setter is neither a function nor a controller method.`,
|
|
1807
|
-
);
|
|
1808
|
-
return true;
|
|
1660
|
+
}
|
|
1661
|
+
Repeater.prototype.recordName = "$record";
|
|
1662
|
+
Repeater.prototype.indexName = "$index";
|
|
1663
|
+
Repeater.prototype.cached = false;
|
|
1664
|
+
Repeater.prototype.immutable = false;
|
|
1665
|
+
Repeater.prototype.sealed = false;
|
|
1666
|
+
Repeater.prototype.isPureContainer = true;
|
|
1667
|
+
Widget.alias("repeater", Repeater);
|
|
1668
|
+
|
|
1669
|
+
class StructuredInstanceDataAccessor {
|
|
1670
|
+
instance;
|
|
1671
|
+
dataConfig;
|
|
1672
|
+
useParentStore;
|
|
1673
|
+
dataSelector;
|
|
1674
|
+
constructor(config) {
|
|
1675
|
+
this.instance = config.instance;
|
|
1676
|
+
this.dataConfig = config.data;
|
|
1677
|
+
this.useParentStore = config.useParentStore;
|
|
1678
|
+
this.dataSelector = getSelector(config.data);
|
|
1679
|
+
if (this.dataSelector.memoize) this.dataSelector = this.dataSelector.memoize();
|
|
1809
1680
|
}
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
this.state = state;
|
|
1813
|
-
this.store.notify();
|
|
1681
|
+
getSelector() {
|
|
1682
|
+
return this.dataSelector;
|
|
1814
1683
|
}
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
this.instanceCache = new InstanceCache(this, this.widget.isPureContainer ? this.key : null);
|
|
1818
|
-
return this.instanceCache;
|
|
1684
|
+
get() {
|
|
1685
|
+
return this.dataSelector.get(this.instance.store.getData());
|
|
1819
1686
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1687
|
+
setItem(key, value) {
|
|
1688
|
+
return this.instance.nestedDataSet(key, value, this.dataConfig, this.useParentStore);
|
|
1822
1689
|
}
|
|
1823
|
-
|
|
1824
|
-
return this.
|
|
1690
|
+
containsKey(key) {
|
|
1691
|
+
return this.dataConfig.hasOwnProperty(key);
|
|
1825
1692
|
}
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
child.detached = true;
|
|
1829
|
-
return child;
|
|
1693
|
+
getKeys() {
|
|
1694
|
+
return Object.keys(this.dataConfig);
|
|
1830
1695
|
}
|
|
1831
|
-
|
|
1832
|
-
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
class Rescope extends PureContainerBase {
|
|
1699
|
+
init() {
|
|
1700
|
+
this.binding = Binding.get(this.bind);
|
|
1701
|
+
if (this.rootAlias) this.rootName = this.rootAlias;
|
|
1702
|
+
super.init();
|
|
1833
1703
|
}
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1704
|
+
initInstance(context, instance) {
|
|
1705
|
+
instance.store = new ZoomIntoPropertyView({
|
|
1706
|
+
store: instance.parentStore,
|
|
1707
|
+
binding: this.binding,
|
|
1708
|
+
rootName: this.rootName,
|
|
1709
|
+
nestedData: isObject(this.data)
|
|
1710
|
+
? new StructuredInstanceDataAccessor({
|
|
1711
|
+
instance,
|
|
1712
|
+
data: this.data,
|
|
1713
|
+
useParentStore: true,
|
|
1714
|
+
})
|
|
1715
|
+
: undefined,
|
|
1842
1716
|
});
|
|
1843
|
-
|
|
1717
|
+
super.initInstance(context, instance);
|
|
1844
1718
|
}
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
const callback = scope[methodName];
|
|
1848
|
-
if (typeof callback === "string") return this.getControllerMethod(callback);
|
|
1849
|
-
if (typeof callback !== "function")
|
|
1850
|
-
throw new Error(`Cannot invoke callback method ${methodName} as assigned value is not a function.`);
|
|
1851
|
-
return callback.bind(scope);
|
|
1719
|
+
applyParentStore(instance) {
|
|
1720
|
+
instance.store.setStore(instance.parentStore);
|
|
1852
1721
|
}
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1722
|
+
}
|
|
1723
|
+
Rescope.prototype.bind = "$page";
|
|
1724
|
+
Rescope.prototype.rootName = "$root";
|
|
1725
|
+
Widget.alias("rescope", Rescope);
|
|
1726
|
+
|
|
1727
|
+
/*
|
|
1728
|
+
* Purpose of FocusManager is to provide focusout notifications.
|
|
1729
|
+
* IE and Firefox do not provide relatedTarget info in blur events which makes it impossible
|
|
1730
|
+
* to determine if focus went outside or stayed inside the component.
|
|
1731
|
+
*/
|
|
1732
|
+
let subscribers$3 = new SubscriberList(),
|
|
1733
|
+
timerInterval = 300,
|
|
1734
|
+
timerId = null;
|
|
1735
|
+
let lastActiveElement = null;
|
|
1736
|
+
let pending = false;
|
|
1737
|
+
class FocusManager {
|
|
1738
|
+
static subscribe(callback) {
|
|
1739
|
+
let unsubscribe = subscribers$3.subscribe(callback);
|
|
1740
|
+
checkTimer();
|
|
1741
|
+
return unsubscribe;
|
|
1742
|
+
}
|
|
1743
|
+
static onFocusOut(el, callback) {
|
|
1744
|
+
let active = isSelfOrDescendant(el, getActiveElement());
|
|
1745
|
+
return this.subscribe((focusedEl) => {
|
|
1746
|
+
if (!active) active = isSelfOrDescendant(el, getActiveElement());
|
|
1747
|
+
else if (!isSelfOrDescendant(el, focusedEl)) {
|
|
1748
|
+
active = false;
|
|
1749
|
+
callback(focusedEl);
|
|
1863
1750
|
}
|
|
1864
|
-
|
|
1865
|
-
}
|
|
1866
|
-
return undefined;
|
|
1751
|
+
});
|
|
1867
1752
|
}
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1753
|
+
static oneFocusOut(el, callback) {
|
|
1754
|
+
this.nudge();
|
|
1755
|
+
let off = this.subscribe((focusedEl) => {
|
|
1756
|
+
if (!isSelfOrDescendant(el, focusedEl)) {
|
|
1757
|
+
callback(focusedEl);
|
|
1758
|
+
off();
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
return off;
|
|
1875
1762
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1763
|
+
static nudge() {
|
|
1764
|
+
if (typeof document !== "undefined" && getActiveElement() !== lastActiveElement) {
|
|
1765
|
+
if (!pending) {
|
|
1766
|
+
pending = true;
|
|
1767
|
+
setTimeout(function () {
|
|
1768
|
+
pending = false;
|
|
1769
|
+
if (getActiveElement() !== lastActiveElement) {
|
|
1770
|
+
lastActiveElement = getActiveElement();
|
|
1771
|
+
batchUpdates(() => {
|
|
1772
|
+
subscribers$3.notify(lastActiveElement);
|
|
1773
|
+
});
|
|
1774
|
+
checkTimer();
|
|
1775
|
+
}
|
|
1776
|
+
}, 0);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1886
1779
|
}
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
* @returns The matching controller cast to the specified type
|
|
1891
|
-
* @throws Error if no controller of the specified type is found
|
|
1892
|
-
*/
|
|
1893
|
-
getControllerByType(type) {
|
|
1894
|
-
const controller = this.findControllerByType(type);
|
|
1895
|
-
if (!controller) throw new Error(`Cannot find a controller of type "${type.name}" in the instance tree.`);
|
|
1896
|
-
return controller;
|
|
1780
|
+
static focus(el) {
|
|
1781
|
+
el.focus();
|
|
1782
|
+
this.nudge();
|
|
1897
1783
|
}
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
if (!controller)
|
|
1903
|
-
throw new Error(
|
|
1904
|
-
`Cannot invoke controller method "${methodName}". The method cannot be found in any of the assigned controllers.`,
|
|
1905
|
-
);
|
|
1906
|
-
return controller[methodName].bind(controller);
|
|
1784
|
+
static focusFirst(el) {
|
|
1785
|
+
let focusable = findFirst(el, isFocusable);
|
|
1786
|
+
if (focusable) this.focus(focusable);
|
|
1787
|
+
return focusable;
|
|
1907
1788
|
}
|
|
1908
|
-
|
|
1909
|
-
|
|
1789
|
+
static focusFirstChild(el) {
|
|
1790
|
+
let focusable = findFirstChild(el, isFocusable);
|
|
1791
|
+
if (focusable) this.focus(focusable);
|
|
1792
|
+
return focusable;
|
|
1910
1793
|
}
|
|
1911
|
-
|
|
1912
|
-
|
|
1794
|
+
static focusNext(el) {
|
|
1795
|
+
let next = el,
|
|
1796
|
+
skip = true;
|
|
1797
|
+
do {
|
|
1798
|
+
if (!skip) {
|
|
1799
|
+
let focusable = this.focusFirst(next);
|
|
1800
|
+
if (focusable) return focusable;
|
|
1801
|
+
}
|
|
1802
|
+
if (next.nextSibling) {
|
|
1803
|
+
next = next.nextSibling;
|
|
1804
|
+
skip = false;
|
|
1805
|
+
} else {
|
|
1806
|
+
next = next.parentNode;
|
|
1807
|
+
skip = true;
|
|
1808
|
+
}
|
|
1809
|
+
} while (next);
|
|
1810
|
+
}
|
|
1811
|
+
static setInterval(interval) {
|
|
1812
|
+
timerInterval = interval;
|
|
1813
|
+
checkTimer();
|
|
1913
1814
|
}
|
|
1914
1815
|
}
|
|
1915
|
-
function
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1816
|
+
function oneFocusOut(component, el, callback) {
|
|
1817
|
+
if (!component.oneFocusOut)
|
|
1818
|
+
component.oneFocusOut = FocusManager.oneFocusOut(el, (focus) => {
|
|
1819
|
+
delete component.oneFocusOut;
|
|
1820
|
+
callback(focus);
|
|
1821
|
+
});
|
|
1921
1822
|
}
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
this.marked = {};
|
|
1927
|
-
this.monitored = null;
|
|
1928
|
-
this.keyPrefix = keyPrefix != null ? keyPrefix + "-" : "";
|
|
1823
|
+
function offFocusOut(component) {
|
|
1824
|
+
if (component.oneFocusOut) {
|
|
1825
|
+
component.oneFocusOut();
|
|
1826
|
+
delete component.oneFocusOut;
|
|
1929
1827
|
}
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1828
|
+
}
|
|
1829
|
+
function preventFocus(e) {
|
|
1830
|
+
//Focus can be prevented only on mousedown event. On touchstart this will not work
|
|
1831
|
+
//preventDefault cannot be used as it prevents scrolling
|
|
1832
|
+
if (e.type !== "mousedown") return;
|
|
1833
|
+
e.preventDefault();
|
|
1834
|
+
unfocusElement(e.currentTarget, false);
|
|
1835
|
+
}
|
|
1836
|
+
function checkTimer() {
|
|
1837
|
+
let shouldRun = !subscribers$3.isEmpty();
|
|
1838
|
+
if (shouldRun && !timerId)
|
|
1839
|
+
timerId = setInterval(() => {
|
|
1840
|
+
FocusManager.nudge();
|
|
1841
|
+
}, timerInterval);
|
|
1842
|
+
if (!shouldRun && timerId) {
|
|
1843
|
+
clearInterval(timerId);
|
|
1844
|
+
timerId = null;
|
|
1944
1845
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1846
|
+
}
|
|
1847
|
+
function preventFocusOnTouch(e, force = false) {
|
|
1848
|
+
if (force || isTouchEvent()) preventFocus(e);
|
|
1849
|
+
}
|
|
1850
|
+
function unfocusElement(target = null, unfocusParentOverlay = true) {
|
|
1851
|
+
const activeElement = getActiveElement();
|
|
1852
|
+
if (!target) target = activeElement;
|
|
1853
|
+
if (unfocusParentOverlay) {
|
|
1854
|
+
let focusableOverlayContainer = closestParent(target, (el) => el.dataset?.focusableOverlayContainer);
|
|
1855
|
+
if (focusableOverlayContainer) target = focusableOverlayContainer;
|
|
1947
1856
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1857
|
+
//find the closest focusable parent of the target element and focus it instead
|
|
1858
|
+
let focusableParent = closestParent(
|
|
1859
|
+
target,
|
|
1860
|
+
(el) => isFocusable(el) && (!unfocusParentOverlay || !!el.dataset?.focusableOverlayContainer),
|
|
1861
|
+
);
|
|
1862
|
+
if (focusableParent && focusableParent !== document.body)
|
|
1863
|
+
focusableParent.focus({
|
|
1864
|
+
preventScroll: true,
|
|
1865
|
+
});
|
|
1866
|
+
else activeElement.blur();
|
|
1867
|
+
FocusManager.nudge();
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
let subscribers$2 = new SubscriberList();
|
|
1871
|
+
class ResizeManager {
|
|
1872
|
+
static subscribe(callback) {
|
|
1873
|
+
return subscribers$2.subscribe(callback);
|
|
1950
1874
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1875
|
+
static notify() {
|
|
1876
|
+
batchUpdates(() => {
|
|
1877
|
+
subscribers$2.notify();
|
|
1878
|
+
});
|
|
1954
1879
|
}
|
|
1955
|
-
|
|
1956
|
-
this.
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
1962
|
-
this.monitored = null;
|
|
1880
|
+
static trackElement(el, callback) {
|
|
1881
|
+
if (typeof ResizeObserver !== "function") return this.subscribe(() => callback([]));
|
|
1882
|
+
let obs = new ResizeObserver(callback);
|
|
1883
|
+
obs.observe(el);
|
|
1884
|
+
return () => {
|
|
1885
|
+
obs.disconnect();
|
|
1886
|
+
};
|
|
1963
1887
|
}
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
if (child === monitoredChild) delete this.children[key];
|
|
1975
|
-
} else activeCount++;
|
|
1976
|
-
}
|
|
1977
|
-
if (activeCount === 0) this.monitored = null;
|
|
1888
|
+
}
|
|
1889
|
+
if (typeof window != "undefined") window.addEventListener("resize", () => ResizeManager.notify());
|
|
1890
|
+
|
|
1891
|
+
let lastZIndex = 10000;
|
|
1892
|
+
class ZIndexManager {
|
|
1893
|
+
static next() {
|
|
1894
|
+
return ++lastZIndex;
|
|
1895
|
+
}
|
|
1896
|
+
static reset(zIndex) {
|
|
1897
|
+
lastZIndex = zIndex;
|
|
1978
1898
|
}
|
|
1979
1899
|
}
|
|
1980
1900
|
|
|
1901
|
+
const Format = Format$1;
|
|
1902
|
+
let cultureSensitiveFormatsRegistered = false;
|
|
1903
|
+
function resolveNumberFormattingFlags(flags) {
|
|
1904
|
+
if (!flags) return null;
|
|
1905
|
+
let result = {};
|
|
1906
|
+
if (flags.indexOf("+") >= 0) result.signDisplay = "exceptZero";
|
|
1907
|
+
if (flags.indexOf("c") >= 0) result.notation = "compact";
|
|
1908
|
+
if (flags.indexOf("a") >= 0) result.currencySign = "accounting";
|
|
1909
|
+
return result;
|
|
1910
|
+
}
|
|
1911
|
+
function enableCultureSensitiveFormatting() {
|
|
1912
|
+
if (cultureSensitiveFormatsRegistered) return;
|
|
1913
|
+
cultureSensitiveFormatsRegistered = true;
|
|
1914
|
+
Format$1.registerFactory(["number", "n"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1915
|
+
let culture = Culture.getNumberCulture();
|
|
1916
|
+
let formatter = culture.getFormatter({
|
|
1917
|
+
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1918
|
+
...resolveNumberFormattingFlags(flags),
|
|
1919
|
+
});
|
|
1920
|
+
return (value) => formatter.format(value);
|
|
1921
|
+
});
|
|
1922
|
+
Format$1.registerFactory("currency", (format, currency, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1923
|
+
let culture = Culture.getNumberCulture();
|
|
1924
|
+
currency = currency || Culture.defaultCurrency;
|
|
1925
|
+
let formatter = culture.getFormatter({
|
|
1926
|
+
style: "currency",
|
|
1927
|
+
currency: currency,
|
|
1928
|
+
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1929
|
+
...resolveNumberFormattingFlags(flags),
|
|
1930
|
+
});
|
|
1931
|
+
return (value) => formatter.format(value);
|
|
1932
|
+
});
|
|
1933
|
+
Format$1.registerFactory(["percentage", "p", "%"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1934
|
+
let culture = Culture.getNumberCulture();
|
|
1935
|
+
let formatter = culture.getFormatter({
|
|
1936
|
+
style: "percent",
|
|
1937
|
+
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1938
|
+
...resolveNumberFormattingFlags(flags),
|
|
1939
|
+
});
|
|
1940
|
+
return (value) => formatter.format(value);
|
|
1941
|
+
});
|
|
1942
|
+
Format$1.registerFactory(["percentSign", "ps"], (format, minimumFractionDigits, maximumFractionDigits, flags) => {
|
|
1943
|
+
let culture = Culture.getNumberCulture();
|
|
1944
|
+
let formatter = culture.getFormatter({
|
|
1945
|
+
style: "percent",
|
|
1946
|
+
...resolveMinMaxFractionDigits(minimumFractionDigits, maximumFractionDigits),
|
|
1947
|
+
...resolveNumberFormattingFlags(flags),
|
|
1948
|
+
});
|
|
1949
|
+
return (value) => formatter.format(value / 100);
|
|
1950
|
+
});
|
|
1951
|
+
Format$1.registerFactory(["date", "d"], (fmt, format = "yyyyMMdd") => {
|
|
1952
|
+
let culture = Culture.getDateTimeCulture();
|
|
1953
|
+
let formatter = culture.getFormatter(format);
|
|
1954
|
+
return (value) => formatter.format(parseDateInvariant(value));
|
|
1955
|
+
});
|
|
1956
|
+
Format$1.registerFactory(["time", "t"], (fmt, format = "hhmmss") => {
|
|
1957
|
+
let culture = Culture.getDateTimeCulture();
|
|
1958
|
+
let formatter = culture.getFormatter(format);
|
|
1959
|
+
return (value) => formatter.format(parseDateInvariant(value));
|
|
1960
|
+
});
|
|
1961
|
+
Format$1.registerFactory(["datetime", "dt"], (fmt, format = "yyyyMd hhmm") => {
|
|
1962
|
+
let culture = Culture.getDateTimeCulture();
|
|
1963
|
+
let formatter = culture.getFormatter(format);
|
|
1964
|
+
return (value) => formatter.format(parseDateInvariant(value));
|
|
1965
|
+
});
|
|
1966
|
+
setGetFormatCacheCallback(() => {
|
|
1967
|
+
let cache = getCurrentCultureCache();
|
|
1968
|
+
if (!cache.formatCache) cache.formatCache = {};
|
|
1969
|
+
return cache.formatCache;
|
|
1970
|
+
});
|
|
1971
|
+
setGetExpressionCacheCallback(() => {
|
|
1972
|
+
let cache = getCurrentCultureCache();
|
|
1973
|
+
if (!cache.exprCache) cache.exprCache = {};
|
|
1974
|
+
return cache.exprCache;
|
|
1975
|
+
});
|
|
1976
|
+
setGetStringTemplateCacheCallback(() => {
|
|
1977
|
+
let cache = getCurrentCultureCache();
|
|
1978
|
+
if (!cache.strTplCache) cache.strTplCache = {};
|
|
1979
|
+
return cache.strTplCache;
|
|
1980
|
+
});
|
|
1981
|
+
GlobalCacheIdentifier.change();
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1981
1984
|
class RenderingContext {
|
|
1982
1985
|
options;
|
|
1983
1986
|
exploreStack;
|
|
@@ -3952,6 +3955,7 @@ class TreeAdapter extends ArrayAdapter {
|
|
|
3952
3955
|
next: new Set(),
|
|
3953
3956
|
};
|
|
3954
3957
|
}
|
|
3958
|
+
if (this.load) this.onLoad = this.load;
|
|
3955
3959
|
}
|
|
3956
3960
|
mapRecords(context, instance, data, parentStore, recordsAccessor) {
|
|
3957
3961
|
const nodes = super.mapRecords(context, instance, data, parentStore, recordsAccessor);
|
|
@@ -3996,9 +4000,9 @@ class TreeAdapter extends ArrayAdapter {
|
|
|
3996
4000
|
this.childrenAccessor,
|
|
3997
4001
|
);
|
|
3998
4002
|
this.processList(context, instance, level + 1, record.key + ":", childNodes, result);
|
|
3999
|
-
} else if (this.
|
|
4003
|
+
} else if (this.onLoad && !dataRecord[this.loadedField] && !dataRecord[this.loadingField]) {
|
|
4000
4004
|
store.set(`${this.recordName}.${this.loadingField}`, true);
|
|
4001
|
-
const response = this.
|
|
4005
|
+
const response = this.onLoad(context, instance, data);
|
|
4002
4006
|
Promise.resolve(response)
|
|
4003
4007
|
.then((children) => {
|
|
4004
4008
|
store.set(`${this.recordName}.${this.childrenField}`, children);
|