estreui 1.0.7 → 1.2.0

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.
@@ -20,6 +20,9 @@ const uis = {
20
20
  dotlottieLoader: "dotlottie-loader",
21
21
 
22
22
  // rim ui //
23
+ prefix: ".prefix",
24
+ suffix: ".suffix",
25
+ divider: ".divider",
23
26
 
24
27
  // component //
25
28
  container: ".container",
@@ -158,6 +161,20 @@ const uis = {
158
161
  paddedDate: ".padded_date",
159
162
  shortDay: ".short_day",
160
163
 
164
+ // live timestamp
165
+ liveTimestamp: "[data-live-timestamp]",
166
+
167
+
168
+ // on click set text
169
+ onClickSetText: "[data-on-click-set-text]",
170
+
171
+ // on click set html
172
+ onClickSetHtml: "[data-on-click-set-html]",
173
+
174
+
175
+ // help alert
176
+ dataHelpAlert: "[data-help-alert]",
177
+
161
178
  // num keypad
162
179
  numKeypad: ".num_keypad",
163
180
 
@@ -170,6 +187,12 @@ const uis = {
170
187
  // toaster slot
171
188
  toasterSlot: ".toaster_slot",
172
189
 
190
+ // multi dial slot
191
+ multiDialSlot: ".multi_dial_slot",
192
+ dialHolder: ".dialHolder",
193
+ dialBound: ".dial_bound",
194
+ dialHost: ".dial_host",
195
+
173
196
 
174
197
  // exported content
175
198
  exportedContent: ".exported_content",
@@ -204,6 +227,7 @@ const eds = {
204
227
  static: "data-static",
205
228
  exported: "data-exported",
206
229
  multiInstance: "data-multi-instance",
230
+ instanceOrigin: "data-instance-origin",
207
231
 
208
232
  // for bind data
209
233
  index: "data-index",
@@ -313,6 +337,8 @@ const eds = {
313
337
  options: "data-options",
314
338
  code: "data-code",
315
339
  value: "data-value",
340
+ align: "data-align",
341
+ initial: "data-initial",
316
342
  intersectionRootMargin: "data-intersection-root-margin",
317
343
  intersectionThreshold: "data-intersection-threshold",
318
344
 
@@ -402,12 +428,32 @@ const eds = {
402
428
  withPrefix: "data-with-prefix",
403
429
  withSuffix: "data-with-suffix",
404
430
 
431
+ // for live timestamp
432
+ liveTimestamp: "data-live-timestamp",
433
+ shortSuffix: "data-short-suffix",
434
+
435
+
436
+ // for on click set text
437
+ onClickSetText: "data-on-click-set-text",
438
+
439
+ // for on click set html
440
+ onClickSetHtml: "data-on-click-set-html",
441
+
442
+
405
443
  // for month selector bar
406
444
  dropdownOpen: "data-dropdown-open",
407
445
  showFuture: "data-show-future",
408
446
  usePopupSelector: "data-use-popup-selector",
409
447
 
410
448
 
449
+ // multi dial slot
450
+ itemTable: "data-item-table", // [['item1', 'item2', 'item3', ...], ['item1', 'item2', 'item3', ...], ...]
451
+ itemAligns: "data-item-aligns", // [t, n, f, ...] :: f: left, n: center, t: right
452
+ itemPrefixes: "data-item-prefixes", // ['prefix1', 'prefix2', ...]
453
+ itemSuffixes: "data-item-suffixes", // ['suffix1', 'suffix2', ...]
454
+ itemDividers: "data-item-dividers", // ['before', 'dividerForAll', 'after'] / ['divider0', 'divider1', ...]
455
+
456
+
411
457
  // for solid point
412
458
  solid: "data-solid",
413
459
 
@@ -662,6 +708,74 @@ const selectionToast = (options = ["option A", "option B", "option C"],
662
708
  ) => toastSelection(title, message, minSelection, maxSelection, options, defaultSelected, callbackConfirm, callbackSelect, callbackDissmiss, callbackAnother, confirm, another);
663
709
 
664
710
 
711
+ function estreToastDials(options = {}) {
712
+ const arrays = [c.table, c.initial, c.aligns, c.prefixes, c.suffixes, c.dividers];
713
+ for (const name of arrays) if (!typeString(options[name])) options[name] = Jcodd.coddify(options[name]);
714
+ options.stretch = !options.stretch ? "" : t1;
715
+ options.hideScrollbar = !options.hideScrollbar ? "" : t1;
716
+ let intent;
717
+ new Promise((resolve) => {
718
+ intent = {
719
+ data: options,
720
+ onConfirm(selections, keys, values) {
721
+ this.data?.callbackConfirm?.(selections, keys, values);
722
+ resolve(selections)
723
+ },
724
+ onSelect(boundIndex, index, value, selectionIndexes, selectionValues) {
725
+ this?.data?.callbackSelect?.(boundIndex, index, value, selectionIndexes, selectionValues);
726
+ },
727
+ onAnother(selections, keys, values) {
728
+ this?.data?.callbackAnother?.(selections, keys, values);
729
+ resolve(false);
730
+ },
731
+ onDissmiss(selections, keys, values) {
732
+ this?.data?.callbackDissmiss?.(selections, keys, values);
733
+ resolve(undefined);
734
+ },
735
+ };
736
+ return pageManager.bringPage("!toastDials", intent);
737
+ });
738
+ return new class {
739
+ get data() { return intent.data; }
740
+ get handle() { return intent.handle; }
741
+ }();
742
+ }
743
+
744
+ const toastDials = (title = "", message = "",
745
+ table = [[]],
746
+ initial = [],
747
+ callbackConfirm = (selections, keys, values) => {},
748
+ callbackSelect = (boundIndex, index, value, selectionIndexes, selectionValues) => {},
749
+ callbackDissmiss = (selections, keys, values) => {},
750
+ callbackAnother = null,
751
+ confirm = isKorean() ? "닫기" : "Close",
752
+ another = isKorean() ? "되돌리기" : "rollback",
753
+ aligns = [],
754
+ prefixes = [],
755
+ suffixes = [],
756
+ dividers = [],
757
+ stretch = t,
758
+ hideScrollbar = t,
759
+ ) => estreToastDials({ title, message, table, initial, aligns, prefixes, suffixes, dividers, stretch, hideScrollbar, callbackConfirm, callbackSelect, callbackDissmiss, callbackAnother, confirm, another });
760
+
761
+ const dialsToast = (table = [[]],
762
+ initial = [],
763
+ title = "", message = "",
764
+ callbackConfirm = (selections, keys, values) => {},
765
+ confirm = isKorean() ? "닫기" : "Close",
766
+ callbackAnother = null,
767
+ another = isKorean() ? "되돌리기" : "rollback",
768
+ callbackDissmiss = (selections, keys, values) => {},
769
+ callbackSelect = (boundIndex, index, value, selectionIndexes, selectionValues) => {},
770
+ aligns = [],
771
+ prefixes = [],
772
+ suffixes = [],
773
+ dividers = [],
774
+ stretch = t,
775
+ hideScrollbar = t,
776
+ ) => toastDials(title, message, table, initial, callbackConfirm, callbackSelect, callbackDissmiss, callbackAnother, confirm, another, aligns, prefixes, suffixes, dividers, stretch, hideScrollbar);
777
+
778
+
665
779
 
666
780
 
667
781
  //override global(window) methods
@@ -772,7 +886,7 @@ prompt = (title,
772
886
 
773
887
  // Infinite loop and prograss meter
774
888
  const waitings = new Set();
775
- let latestIO = null;
889
+ // let latestIO = null;
776
890
  let backHolds = 0;
777
891
 
778
892
  /**
@@ -781,8 +895,8 @@ let backHolds = 0;
781
895
  * @param {instanceOrigin: string} / instance access origin code
782
896
  */
783
897
  const wait = function (options, instanceOrigin = "wait_" + Date.now()) {
784
- if (instanceOrigin != n) waitings.add(instanceOrigin);
785
- latestIO = instanceOrigin;
898
+ // if (instanceOrigin != n) waitings.add(instanceOrigin);
899
+ // latestIO = instanceOrigin;
786
900
  pageManager.bringPage("!onRunning", { data: options }, instanceOrigin);
787
901
  return instanceOrigin;
788
902
  }
@@ -795,15 +909,18 @@ const wait = function (options, instanceOrigin = "wait_" + Date.now()) {
795
909
  */
796
910
  const stedy = function (options, delay = 600, instanceOrigin = "stedy_" + Date.now()) {
797
911
  if (instanceOrigin != n) waitings.add(instanceOrigin);
798
- latestIO = instanceOrigin;
912
+ // latestIO = instanceOrigin;
799
913
  setTimeout(_ => {
800
- if (latestIO == instanceOrigin) wait(options, instanceOrigin);
914
+ if (waitings.has(instanceOrigin)) {
915
+ waitings.delete(instanceOrigin);
916
+ wait(options, instanceOrigin);
917
+ }
801
918
  }, delay);
802
919
  return instanceOrigin;
803
920
  }
804
921
 
805
922
  const onBackWhile = function (handle) {
806
- if (handle != n || latestIO != n) {
923
+ if (handle != n) {// || latestIO != n) {
807
924
  backHolds++;
808
925
  return t;
809
926
  }
@@ -816,20 +933,24 @@ const onBackWhile = function (handle) {
816
933
  * @param {instanceOrigin} / instance access origin code
817
934
  */
818
935
  const go = function (instanceOrigin) {
819
- if (instanceOrigin != n) {
820
- if (waitings.has(instanceOrigin) == f) return;
936
+ // if (instanceOrigin != n) {
937
+ // if (waitings.has(instanceOrigin) == f) return;
938
+ // waitings.delete(instanceOrigin);
939
+ // if (latestIO != instanceOrigin && waitings.size > 0) return;
940
+ // }
941
+ if (instanceOrigin != n && waitings.has(instanceOrigin)) {
821
942
  waitings.delete(instanceOrigin);
822
- if (latestIO != instanceOrigin && waitings.size > 0) return;
943
+ // return instanceOrigin;
823
944
  }
824
945
  const aio = pageManager.closePage("!onRunning", f, instanceOrigin);
825
- latestIO = n;
946
+ // latestIO = n;
826
947
  if (backHolds > 0) postAsyncQueue(async _ => {
827
948
  const holds = backHolds;
828
949
  backHolds = 0;
829
950
  await aio;
830
951
  if (window.isLogging) console.log("Release holded back requests");
831
- // for (let i=0; i<holds; i++) await estreUi.onBack();
832
- await estreUi.onBack();
952
+ for (let i=0; i<holds; i++) await estreUi.onBack();
953
+ // await estreUi.onBack();
833
954
  })
834
955
  return aio;
835
956
  }
@@ -1454,14 +1575,20 @@ class EstrePageHandle {
1454
1575
 
1455
1576
  hostType = "unknown";
1456
1577
 
1457
- host = null
1578
+ #host = null;
1579
+ get host() { return this.#host; }
1580
+ #$host = null;
1581
+ get $host() { return this.#$host; }
1458
1582
 
1459
- host = null;
1460
- $host = null;
1461
1583
  id = null;
1584
+ get instanceId() { return !this.isStatic && this.isMultiInstance ? this.id + "^" + this.instanceOrigin : this.id; }
1585
+ get instanceOrigin() { return !this.isStatic && this.isMultiInstance ? this.$host?.attr(eds.instanceOrigin)?.ifEmpty(_ => u) : u; }
1586
+ set instanceOrigin(value) { if (!this.isStatic && this.isMultiInstance) this.$host?.attr(eds.instanceOrigin, value ?? ""); }
1462
1587
 
1463
- page = null;
1464
- pid = null;
1588
+ #page = null;
1589
+ get page() { return this.#page; }
1590
+ get pid() { return this.page?.pid; }
1591
+ get instancePid() { return this.page?.instancePid; }
1465
1592
 
1466
1593
  get isStatic() { return this.$host?.attr(eds.static) == t1; }
1467
1594
  get isFullyStatic() { return this.isStatic; }
@@ -1470,6 +1597,7 @@ class EstrePageHandle {
1470
1597
  const onTop = this.$host?.attr(eds.onTop);
1471
1598
  return onTop == t1 || onTop == "1*";
1472
1599
  }
1600
+ get isMultiInstance() { return this.$host?.attr(eds.multiInstance) == t1; }
1473
1601
 
1474
1602
  get isCanBack() { return false; }
1475
1603
 
@@ -1546,24 +1674,29 @@ class EstrePageHandle {
1546
1674
  #intentProxy;
1547
1675
  #intentDataProxy;
1548
1676
  #intentDataBindProxy = {};
1549
- #revokeIntentProxy;
1550
- #revokeIntentDataProxy;
1551
- #revokeIntentDataBindProxy = {};
1677
+ // #revokeIntentProxy;
1678
+ // #revokeIntentDataProxy;
1679
+ // #revokeIntentDataBindProxy = {};
1552
1680
 
1553
1681
  #isProcessing = f;
1682
+ get isProcessing() { return this.#isProcessing; }
1683
+
1684
+ get mainArticle() { return this; }
1554
1685
 
1555
- constructor(host) {
1556
- this.host = host;
1557
- this.$host = $(host);
1558
1686
 
1559
- if (this.host.pageHandle != null && this.host.pageHandle != this) {
1687
+ constructor(host, instanceOrigin) {
1688
+ this.#host = host;
1689
+ this.#$host = $(host);
1690
+
1691
+ if (host.pageHandle != null && host.pageHandle != this) {
1560
1692
  try {
1561
- this.host.pageHandle.release();
1693
+ host.pageHandle.release();
1562
1694
  } catch (ex) {
1563
1695
  if (window.isLogging) console.error(ex.name + "\n", ex.message);
1564
1696
  }
1565
1697
  }
1566
- this.host.pageHandle = this;
1698
+ this.#host.pageHandle = this;
1699
+ if (!this.isStatic && this.isMultiInstance) this.instanceOrigin = instanceOrigin ?? "ai_" + Date.now();
1567
1700
  }
1568
1701
 
1569
1702
  release(remove) {
@@ -1574,14 +1707,13 @@ class EstrePageHandle {
1574
1707
  if (remove === true) this.$host?.remove();
1575
1708
  else {
1576
1709
  if (remove === false) this.$host?.empty();
1577
- this.host = n;
1578
- this.$host = n;
1710
+ this.#host = n;
1711
+ this.#$host = n;
1579
1712
  }
1580
1713
  }
1581
1714
 
1582
1715
  init(page, intent) {
1583
- this.page = page;
1584
- this.pid = page.pid;
1716
+ this.#page = page;
1585
1717
  page.fetchHandler(this);
1586
1718
  if (this.handler == null) this.setHandler(new EstrePageHandler(this));
1587
1719
 
@@ -1597,14 +1729,15 @@ class EstrePageHandle {
1597
1729
  }
1598
1730
 
1599
1731
  takeOnPageIntent(intent = {}) {
1600
- this.#revokeIntentProxy?.();
1732
+ // this.#revokeIntentProxy?.();
1601
1733
  if (nn(intent?.data) && !intent.data.isProxy) intent.data = this.takeOnPageData(intent.data);
1602
- const { proxy, revoke } = nn(intent) ? Proxy.revocable(intent, {
1734
+ // const { proxy, revoke } = nn(intent) ? Proxy.revocable(intent, {
1735
+ const proxy = nn(intent) ? new Proxy(intent, {
1603
1736
  get: (target, prop) => prop == "isProxy" ? t : target[prop],
1604
1737
  set: (target, prop, value) => {
1605
1738
  if (prop == "data") {
1606
1739
  target.data = this.takeOnPageData(value);
1607
- if (!this.#isProcessing) this.applyActiveStruct();
1740
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1608
1741
  } else target[prop] = value;
1609
1742
  return t;
1610
1743
  },
@@ -1613,81 +1746,85 @@ class EstrePageHandle {
1613
1746
  this.takeOnPageData(u);
1614
1747
  delete target.data;
1615
1748
  } else delete target[prop];
1616
- if (!this.#isProcessing) this.applyActiveStruct();
1749
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1617
1750
  return t;
1618
1751
  },
1619
- }) : { proxy: u, revoke: u };
1752
+ }) : u;//{ proxy: u, revoke: u };
1620
1753
  this.#intentProxy = proxy;
1621
- this.#revokeIntentProxy = revoke;
1754
+ // this.#revokeIntentProxy = revoke;
1622
1755
  return proxy ?? intent;
1623
1756
  }
1624
1757
 
1625
1758
  takeOnPageData(data = {}) {
1626
- this.#revokeIntentDataProxy?.();
1759
+ // this.#revokeIntentDataProxy?.();
1627
1760
  const isObject = nn(data) && tj(data);
1628
1761
  if (isObject) for (const key in data) if (!data[key]?.isProxy) data[key] = this.takeOnPageBind(key, data[key]);
1629
- const { proxy, revoke } = isObject ? Proxy.revocable(data, {
1762
+ // const { proxy, revoke } = isObject ? Proxy.revocable(data, {
1763
+ const proxy = isObject ? new Proxy(data, {
1630
1764
  get: (target, prop) => prop == "isProxy" ? t : target[prop],
1631
1765
  set: (target, prop, value) => {
1632
1766
  target[prop] = this.takeOnPageBind(prop, value);
1633
- if (!this.#isProcessing) this.applyActiveStruct();
1767
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1634
1768
  return t;
1635
1769
  },
1636
1770
  deleteProperty: (target, prop) => {
1637
1771
  this.takeOnPageBind(prop, u);
1638
1772
  delete target[prop];
1639
- if (!this.#isProcessing) this.applyActiveStruct();
1773
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1640
1774
  return t;
1641
1775
  },
1642
- }) : { proxy: u, revoke: u };
1776
+ }) : u;//{ proxy: u, revoke: u };
1643
1777
  this.#intentDataProxy = proxy;
1644
- this.#revokeIntentDataProxy = revoke;
1778
+ // this.#revokeIntentDataProxy = revoke;
1645
1779
  return proxy ?? data;
1646
1780
  }
1647
1781
 
1648
1782
  takeOnPageBind(pr, bind) {
1649
- const rv = this.#revokeIntentDataBindProxy[pr];
1650
- if (tf(rv)) rv();
1783
+ // const rv = this.#revokeIntentDataBindProxy[pr];
1784
+ // if (tf(rv)) rv();
1651
1785
  if (nn(bind) && tj(bind)) {
1652
- const { proxy, revoke } = Proxy.revocable(bind, {
1786
+ // const { proxy, revoke } = Proxy.revocable(bind, {
1787
+ const proxy = new Proxy(bind, {
1653
1788
  get: (target, prop) => prop == "isProxy" ? t : target[prop],
1654
1789
  set: (target, prop, value) => {
1655
1790
  target[prop] = value;
1656
- if (!this.#isProcessing) this.applyActiveStruct();
1791
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1657
1792
  return t;
1658
1793
  },
1659
1794
  deleteProperty: (target, prop) => {
1660
1795
  delete target[prop];
1661
- if (!this.#isProcessing) this.applyActiveStruct();
1796
+ if (!this.mainArticle.isProcessing) this.mainArticle.applyActiveStruct(this.mainArticle.$host, this);
1662
1797
  return t;
1663
1798
  },
1664
1799
  });
1665
1800
  this.#intentDataBindProxy[pr] = proxy;
1666
- this.#revokeIntentDataBindProxy[pr] = revoke;
1801
+ // this.#revokeIntentDataBindProxy[pr] = revoke;
1667
1802
  return proxy;
1668
1803
  } else {
1669
1804
  delete this.#intentDataBindProxy[pr];
1670
- delete this.#revokeIntentDataBindProxy[pr];
1805
+ // delete this.#revokeIntentDataBindProxy[pr];
1671
1806
  return bind;
1672
1807
  }
1673
1808
  }
1674
1809
 
1675
- apply(process = (data, intent) => {}, $bound = this.$host) {
1810
+ apply(process = (data, intent) => {}, $bound = this.mainArticle.$host, handle = this) {
1811
+ if (this.mainArticle != this) return this.mainArticle.apply(process, $bound, this);
1676
1812
  const isAlreadyProcessing = this.#isProcessing;
1677
1813
  if (!isAlreadyProcessing) this.#isProcessing = t;
1678
1814
  this.placeIntentData();
1679
1815
  process(this.intent.data, this.intent);
1680
1816
  if (!isAlreadyProcessing) this.#isProcessing = f;
1681
- return this.applyActiveStruct($bound);
1817
+ return this.applyActiveStruct($bound, handle);
1682
1818
  }
1683
1819
 
1684
- async applyAsync(process = async (data, intent) => {}, $bound = this.$host) {
1820
+ async applyAsync(process = async (data, intent) => {}, $bound = this.mainArticle.$host, handle = this) {
1821
+ if (this.mainArticle != this) return await this.mainArticle.applyAsync(process, $bound, handle);
1685
1822
  const isAlreadyProcessing = this.#isProcessing;
1686
1823
  if (!isAlreadyProcessing) this.#isProcessing = t;
1687
1824
  this.placeIntentData();
1688
1825
  await process(this.intent.data, this.intent);
1689
1826
  if (!isAlreadyProcessing) this.#isProcessing = f;
1690
- return await this.applyActiveStruct($bound);
1827
+ return await this.applyActiveStruct($bound, handle);
1691
1828
  }
1692
1829
 
1693
1830
  placeIntent(intent = {}) {
@@ -1929,11 +2066,11 @@ class EstrePageHandle {
1929
2066
  if (this.handler?.onRelease != null) await this.handler.onRelease(this, remove);
1930
2067
  if (this.intent?.onRelease != null) for (var item of this.intent.onRelease) if (item.from == this.hostType && !item.disabled) await this.processAction(item);
1931
2068
 
1932
- for (const revoke of this.#revokeIntentDataBindProxy.looks) try {
1933
- revoke?.();
1934
- } catch (ex) {}
1935
- this.#revokeIntentDataProxy?.();
1936
- this.#revokeIntentProxy?.();
2069
+ // for (const revoke of this.#revokeIntentDataBindProxy.looks) try {
2070
+ // revoke?.();
2071
+ // } catch (ex) {}
2072
+ // this.#revokeIntentDataProxy?.();
2073
+ // this.#revokeIntentProxy?.();
1937
2074
  return true;
1938
2075
  } else return false;
1939
2076
  }
@@ -1967,11 +2104,13 @@ class EstrePageHandle {
1967
2104
 
1968
2105
 
1969
2106
  // active struct master
1970
- applyActiveStruct($host = this.$host, replaceHandles = false) {
2107
+ applyActiveStruct($host = this.$host, handle = this, replaceHandles = false) {
1971
2108
  this.initContentBrokers($host);
1972
2109
  this.initLiveElement($host, replaceHandles);
1973
2110
 
1974
- return this.handler.onApplied?.(this, this.intent?.data, this.intent, $host, replaceHandles);
2111
+ const applied = this.handler.onApplied?.(this, this.intent?.data, this.intent, $host, replaceHandles);
2112
+ if (handle != this) handle.handler.onApplied?.(handle, handle.intent?.data, handle.intent, $host, replaceHandles);
2113
+ return applied;
1975
2114
  }
1976
2115
 
1977
2116
  applyActiveStructLocalBind($host = this.$host) {
@@ -1998,11 +2137,11 @@ class EstrePageHandle {
1998
2137
  const eachTarget = ($elem, attrId, each = (target, prefix = "", suffix = "") => {}) => {
1999
2138
  const specifier = $elem.attr(attrId);
2000
2139
  if (specifier != null && specifier != "") {
2001
- const targets = specifier.split(" ");
2140
+ const targets = specifier.split(s);
2002
2141
  for (let target of targets) {
2003
2142
  let prefix = "", suffix = "";
2004
- if (target.indexOf("^") > -1) [target, prefix] = target.split("^");
2005
- if (target.indexOf("$") > -1) [suffix, target] = target.split("$");
2143
+ if (target.indexOf(cf) > -1) [target, prefix] = target.split(cf);
2144
+ if (target.indexOf(ds) > -1) [suffix, target] = target.split(ds);
2006
2145
  each(target, prefix, suffix);
2007
2146
  }
2008
2147
  }
@@ -2010,12 +2149,12 @@ class EstrePageHandle {
2010
2149
  const eachTargetFor = ($elem, attrId, each = (targetItem, targetName, prefix = "", suffix = "") => {}) => {
2011
2150
  const specifier = $elem.attr(attrId);
2012
2151
  if (specifier != null && specifier != "") {
2013
- const targets = specifier.split(" ");
2152
+ const targets = specifier.split(s);
2014
2153
  for (const target of targets) {
2015
- let [targetItem, targetName] = target.split("@");
2154
+ let [targetItem, targetName] = target.split(at);
2016
2155
  let prefix = "", suffix = "";
2017
- if (targetItem.indexOf("^") > -1) [targetItem, prefix] = targetItem.split("^");
2018
- if (targetItem.indexOf("$") > -1) [suffix, targetItem] = targetItem.split("$");
2156
+ if (targetItem.indexOf(cf) > -1) [targetItem, prefix] = targetItem.split(cf);
2157
+ if (targetItem.indexOf(ds) > -1) [suffix, targetItem] = targetItem.split(ds);
2019
2158
  each(targetItem, targetName, prefix, suffix);
2020
2159
  }
2021
2160
  }
@@ -2036,20 +2175,20 @@ class EstrePageHandle {
2036
2175
  $host.find(aiv(eds.bindAmount, item)).html(v2a(value));
2037
2176
  $host.find(aiv(eds.bindValue, item)).val(value);
2038
2177
 
2039
- if ($host.is(acv(eds.bindAttr, item + "@"))) eachTargetFor($host, eds.bindAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2178
+ if ($host.is(acv(eds.bindAttr, item) + acv(eds.bindAttr, at))) eachTargetFor($host, eds.bindAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2040
2179
  if (targetItem == item) $host.attr(targetAttr, prefix + value + suffix);
2041
2180
  });
2042
- $host.find(acv(eds.bindAttr, item + "@")).each((i, elem) => {
2181
+ $host.find(acv(eds.bindAttr, item) + acv(eds.bindAttr, at)).each((i, elem) => {
2043
2182
  const $elem = $(elem);
2044
2183
  eachTargetFor($elem, eds.bindAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2045
2184
  if (targetItem == item) $elem.attr(targetAttr, prefix + value + suffix);
2046
2185
  });
2047
2186
  });
2048
2187
 
2049
- if ($host.find(acv(eds.bindStyle, item + "@"))) eachTargetFor($host, eds.bindStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2188
+ if ($host.find(acv(eds.bindStyle, item) + acv(eds.bindStyle, at))) eachTargetFor($host, eds.bindStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2050
2189
  if (targetItem == item) $host.css(targetStyle, prefix + value + suffix);
2051
2190
  });
2052
- $host.find(acv(eds.bindStyle, item + "@")).each((i, elem) => {
2191
+ $host.find(acv(eds.bindStyle, item) + acv(eds.bindStyle, at)).each((i, elem) => {
2053
2192
  const $elem = $(elem);
2054
2193
  eachTargetFor($elem, eds.bindStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2055
2194
  if (targetItem == item) $elem.css(targetStyle, prefix + value + suffix);
@@ -2112,10 +2251,10 @@ class EstrePageHandle {
2112
2251
  $li.find(aiv(eds.bindObjectArrayAmount, objItem)).html(v2a(value));
2113
2252
  $li.find(aiv(eds.bindObjectArrayValue, objItem)).val(value);
2114
2253
 
2115
- if ($li.is(acv(eds.bindObjectArrayAttr, objItem + "@"))) eachTargetFor($li, eds.bindObjectArrayAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2254
+ if ($li.is(acv(eds.bindObjectArrayAttr, objItem) + acv(eds.bindObjectArrayAttr, at))) eachTargetFor($li, eds.bindObjectArrayAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2116
2255
  if (targetItem == objItem) $li.attr(targetAttr, prefix + value + suffix);
2117
2256
  });
2118
- $li.find(acv(eds.bindObjectArrayAttr, objItem + "@")).each((i, elem) => {
2257
+ $li.find(acv(eds.bindObjectArrayAttr, objItem) + acv(eds.bindObjectArrayAttr, at)).each((i, elem) => {
2119
2258
  const $elem = $(elem);
2120
2259
  eachTargetFor($elem, eds.bindObjectArrayAttr, (targetItem, targetAttr, prefix = "", suffix = "") => {
2121
2260
  if (targetItem == objItem) $elem.attr(targetAttr, prefix + value + suffix);
@@ -2124,10 +2263,10 @@ class EstrePageHandle {
2124
2263
 
2125
2264
  const styleValue = isEmpty(value) ? "unset" : value;
2126
2265
 
2127
- if ($li.is(acv(eds.bindObjectArrayStyle, objItem + "@"))) eachTargetFor($li, eds.bindObjectArrayStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2266
+ if ($li.is(acv(eds.bindObjectArrayStyle, objItem) + acv(eds.bindObjectArrayStyle, at))) eachTargetFor($li, eds.bindObjectArrayStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2128
2267
  if (targetItem == objItem) $li.css(targetStyle, prefix + styleValue + suffix);
2129
2268
  });
2130
- $li.find(acv(eds.bindObjectArrayStyle, objItem + "@")).each((i, elem) => {
2269
+ $li.find(acv(eds.bindObjectArrayStyle, objItem) + acv(eds.bindObjectArrayStyle, at)).each((i, elem) => {
2131
2270
  const $elem = $(elem);
2132
2271
  eachTargetFor($elem, eds.bindObjectArrayStyle, (targetItem, targetStyle, prefix = "", suffix = "") => {
2133
2272
  if (targetItem == objItem) $elem.css(targetStyle, prefix + styleValue + suffix);
@@ -2687,13 +2826,27 @@ class EstrePageHostHandle extends EstrePageHandle {
2687
2826
 
2688
2827
  get currentTop() { return this.currentOnTop ?? this.subPageList.at(-1); }
2689
2828
 
2690
- #prevSubPageId = null;
2691
- get prevSubPageId() { return this.#prevSubPageId; };
2692
- set prevSubPageId(id) {
2693
- this.#prevSubPageId = id;
2829
+ #prevSubPageIds = new Set();
2830
+ get latestSubPageId() { return [...this.#prevSubPageIds].pop(); }
2831
+ get prevSubPageId() {
2832
+ const subPageIds = this.subPages.ways;
2833
+ let latestSubPageId = null;
2834
+ while (latestSubPageId = this.latestSubPageId) {
2835
+ this.#prevSubPageIds.delete(latestSubPageId);
2836
+ if (subPageIds.includes(latestSubPageId)) return latestSubPageId;
2837
+ }
2838
+ return null;
2839
+ };
2840
+ set prevSubPageId(id) {
2841
+ if (id == null) return;
2842
+ if (this.#prevSubPageIds.has(id)) this.$prevSubPages.delete(id);
2843
+ this.#prevSubPageIds.add(id);
2694
2844
  };
2695
2845
 
2696
- get isAvailablePrevSubPage() { return this.prevSubPageId != null && this.subPages[this.prevSubPageId] != null; }
2846
+ get isAvailablePrevSubPage() {
2847
+ const latestSubPageId = this.latestSubPageId;
2848
+ return latestSubPageId != null && this.subPages[latestSubPageId] != null;
2849
+ }
2697
2850
 
2698
2851
 
2699
2852
  initSubPages(intent) {
@@ -2709,19 +2862,19 @@ class EstrePageHostHandle extends EstrePageHandle {
2709
2862
  }
2710
2863
 
2711
2864
 
2712
- showSubPage(id, intent) {
2865
+ showSubPage(id, intent, instanceOrigin) {
2713
2866
  return false;
2714
2867
  }
2715
2868
 
2716
- openSubPage(id, intent) {
2869
+ openSubPage(id, intent, instanceOrigin) {
2717
2870
  return false;
2718
2871
  }
2719
2872
 
2720
- bringSubPage(id, intent) {
2873
+ bringSubPage(id, intent, instanceOrigin) {
2721
2874
  return false;
2722
2875
  }
2723
2876
 
2724
- closeSubPage(id, isTermination = false) {
2877
+ closeSubPage(id, instanceOrigin, isTermination = false) {
2725
2878
 
2726
2879
  }
2727
2880
 
@@ -2762,12 +2915,13 @@ class EstreComponent extends EstrePageHostHandle {
2762
2915
  if (registered === false) return false;
2763
2916
  this.unregister(component);
2764
2917
  this.componentList.push(component);
2765
- this.components[component.id] = component;
2918
+ this.components[component.instanceId] = component;
2766
2919
  return registered;
2767
2920
  }
2768
2921
 
2769
2922
  static unregister(component) {
2770
- if (this.components[component.id] != null) delete this.components[component.id];
2923
+ const instanceId = component.instanceId;
2924
+ if (this.components[instanceId] != null) delete this.components[instanceId];
2771
2925
  const index = this.componentList.indexOf(component);
2772
2926
  if (index > -1) this.componentList.splice(index, 1);
2773
2927
  return EstreUiPage.unregisterFrom(component);
@@ -2777,7 +2931,8 @@ class EstreComponent extends EstrePageHostHandle {
2777
2931
  // instance property
2778
2932
  get isCanBack() { switch (this.sectionBound) {
2779
2933
  case "main":
2780
- return !this.isHome && ((estreUi.prevRootTabId != null && estreUi.mainSections[estreUi.prevRootTabId] != null) || estreUi.mainSections["home"] != null);
2934
+ const latestRootTabId = estreUi.latestRootTabId;
2935
+ return !this.isHome && ((latestRootTabId != null && estreUi.mainSections[latestRootTabId] != null) || estreUi.mainSections["home"] != null);
2781
2936
 
2782
2937
  case "blind":
2783
2938
  case "menu":
@@ -2815,8 +2970,8 @@ class EstreComponent extends EstrePageHostHandle {
2815
2970
 
2816
2971
  get isHome() { return this.id == "home" || this.$host.hasClass("home"); }
2817
2972
 
2818
- constructor(component) {
2819
- super(component);
2973
+ constructor(component, instanceOrigin) {
2974
+ super(component, instanceOrigin);
2820
2975
  this.id = component.id;
2821
2976
  }
2822
2977
 
@@ -2851,8 +3006,8 @@ class EstreComponent extends EstrePageHostHandle {
2851
3006
  return this.initContainers(intent);
2852
3007
  }
2853
3008
 
2854
- registerSubPage(element, intent) {
2855
- return this.registerContainer(element, intent);
3009
+ registerSubPage(element, intent, instanceOrigin) {
3010
+ return this.registerContainer(element, intent, instanceOrigin);
2856
3011
  }
2857
3012
 
2858
3013
  unregisterSubPage(pageHandle) {
@@ -2872,11 +3027,12 @@ class EstreComponent extends EstrePageHostHandle {
2872
3027
  $top[$top.length - 1]?.pageHandle?.show(false, false);
2873
3028
  }
2874
3029
 
2875
- registerContainer(element, intent) {
3030
+ registerContainer(element, intent, instanceOrigin) {
2876
3031
  this.unregisterConatiner(element.pageHandle);
2877
- const container = new EstreContainer(element, this);
2878
- this.$container[container.id] = container.$host;
2879
- this.containers[container.id] = container;
3032
+ const container = new EstreContainer(element, this, instanceOrigin);
3033
+ const instanceId = container.instanceId;
3034
+ this.$container[instanceId] = container.$host;
3035
+ this.containers[instanceId] = container;
2880
3036
  this.containerList.push(container);
2881
3037
  const registered = EstreUiPage.registerOrCommitFrom(container);
2882
3038
  container.init(registered, intent);
@@ -2886,10 +3042,11 @@ class EstreComponent extends EstrePageHostHandle {
2886
3042
 
2887
3043
  unregisterConatiner(container) {
2888
3044
  if (container == null) return;
3045
+ const instanceId = container.instanceId;
2889
3046
  const unregitered = EstreUiPage.unregisterFrom(container);
2890
3047
  container.release(!container.isStatic ? true : null);
2891
- if (this.$container[container.id] != null) delete this.$container[container.id];
2892
- if (this.containers[container.id] != null) delete this.containers[container.id];
3048
+ if (this.$container[instanceId] != null) delete this.$container[instanceId];
3049
+ if (this.containers[instanceId] != null) delete this.containers[instanceId];
2893
3050
  const index = this.containerList.indexOf(container);
2894
3051
  if (index > -1) this.containerList.splice(index, 1);
2895
3052
  return unregitered;
@@ -2897,29 +3054,28 @@ class EstreComponent extends EstrePageHostHandle {
2897
3054
 
2898
3055
 
2899
3056
  // handles
2900
- showSubPage(id, intent) {
2901
- return this.showContainer(id, intent);
3057
+ showSubPage(id, intent, instanceOrigin) {
3058
+ return this.showContainer(id, intent, instanceOrigin);
2902
3059
  }
2903
3060
 
2904
- openSubPage(id, intent) {
2905
- return this.openContainer(id, intent);
3061
+ openSubPage(id, intent, instanceOrigin) {
3062
+ return this.openContainer(id, intent, instanceOrigin);
2906
3063
  }
2907
3064
 
2908
- bringSubPage(id, intent) {
2909
- return this.bringContainer(id, intent);
3065
+ bringSubPage(id, intent, instanceOrigin) {
3066
+ return this.bringContainer(id, intent, instanceOrigin);
2910
3067
  }
2911
3068
 
2912
- closeSubPage(id, isTermination = false) {
2913
- return this.closeContainer(id, isTermination);
3069
+ closeSubPage(id, instanceOrigin, isTermination = false) {
3070
+ return this.closeContainer(id, instanceOrigin, isTermination);
2914
3071
  }
2915
3072
 
2916
- showContainer(id, intent) {
3073
+ showContainer(id, intent, instanceOrigin) {
2917
3074
  if (id != null && !this.isClosing) {
2918
- const container = this.containers[id];
2919
- if (container != null) {
3075
+ const show = container => {
2920
3076
  const currentTopHandle = this.currentTop;
2921
- const currentTopHandleId = currentTopHandle.id;
2922
- if (id != currentTopHandleId && currentTopHandleId != this.prevSubPageId) {
3077
+ const currentTopHandleId = currentTopHandle.instanceId;
3078
+ if (id != currentTopHandleId && currentTopHandleId != this.latestSubPageId) {
2923
3079
  this.prevSubPageId = currentTopHandleId;
2924
3080
 
2925
3081
  // if (estreUi.euiState == "onReady" && currentTopHandle != null) switch (currentTopHandle.sectionBound) {
@@ -2944,12 +3100,23 @@ class EstreComponent extends EstrePageHostHandle {
2944
3100
  break;
2945
3101
  }
2946
3102
  return true;
3103
+ };
3104
+
3105
+ const container = this.containers[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
3106
+ if (container != null) return show(container);
3107
+ else if (instanceOrigin == n) {
3108
+ const containerIds = this.containers.ways.filter(it => it.startsWith(id + "^"));
3109
+ if (containerIds.length > 0) {
3110
+ const containerId = containerIds[containerIds.length - 1];
3111
+ const container = this.containers[containerId];
3112
+ if (container != null) return show(container);
3113
+ }
2947
3114
  }
2948
3115
  }
2949
3116
  return false;
2950
3117
  }
2951
3118
 
2952
- openContainer(id, intent) {
3119
+ openContainer(id, intent, instanceOrigin) {
2953
3120
  if (this.isClosing) return false;
2954
3121
  const page = pageManager.getConatiner(id, this.id, this.sectionBound);
2955
3122
  if (page == null) return null;
@@ -2957,13 +3124,12 @@ class EstreComponent extends EstrePageHostHandle {
2957
3124
  this.$host.append(page.live);
2958
3125
  const $container = this.$containers.filter(aiv(eds.containerId, id));
2959
3126
  if ($container == null || $container.length < 1) return null;
2960
- return this.registerContainer($container[0], intent);
3127
+ return this.registerContainer($container[$container.length - 1], intent, instanceOrigin);
2961
3128
  }
2962
3129
 
2963
- closeContainer(id, isTermination = false) {
3130
+ closeContainer(id, instanceOrigin, isTermination = false) {
2964
3131
  if (id != null) {
2965
- const container = this.containers[id];
2966
- if (container != null) {
3132
+ const close = container => {
2967
3133
  const task = container.close(false, isTermination || !container.isStatic);
2968
3134
  if (!isTermination && !this.isClosing) postAsyncQueue(async _ => {
2969
3135
  if (this.isClosing) return;
@@ -2971,9 +3137,8 @@ class EstreComponent extends EstrePageHostHandle {
2971
3137
  const subPageList = this.subPageList.filter(it => !it.isClosing && it != target);
2972
3138
  if (subPageList.length > 0) {
2973
3139
  const prev = this.prevSubPageId;
2974
- if (prev != null && id != prev && this.subPages[prev] != null) {
2975
- if (this.showSubPage(prev)) this.prevSubPageId = null;
2976
- } else subPageList[subPageList.length - 1].show();
3140
+ if (prev != null) this.showSubPage(prev);
3141
+ else subPageList[subPageList.length - 1].show();
2977
3142
  } else {
2978
3143
  await task;
2979
3144
  if (!this.isClosing && !this.isStatic && subPageList.length < 1) this.close(true, true);
@@ -2984,16 +3149,27 @@ class EstreComponent extends EstrePageHostHandle {
2984
3149
  if (isTermination || !container.isStatic) this.unregisterConatiner(container);
2985
3150
  return result;
2986
3151
  });
3152
+ };
3153
+
3154
+ const container = this.containers[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
3155
+ if (container != null) return close(container);
3156
+ else if (instanceOrigin == n) {
3157
+ const containerIds = this.containers.ways.filter(it => it.startsWith(id + "^"));
3158
+ if (containerIds.length > 0) {
3159
+ const containerId = containerIds[containerIds.length - 1];
3160
+ const container = this.containers[containerId];
3161
+ return close(container);
3162
+ }
2987
3163
  }
2988
3164
  }
2989
3165
  return null;
2990
3166
  }
2991
3167
 
2992
- bringContainer(id, intent) {
3168
+ bringContainer(id, intent, instanceOrigin) {
2993
3169
  if (this.containers[id] == null) {
2994
- if (this.openContainer(id, intent)) return this.showContainer(id);
3170
+ if (this.openContainer(id, intent, instanceOrigin)) return this.showContainer(id, u, instanceOrigin);
2995
3171
  else return false;
2996
- } else return this.showContainer(id, intent);
3172
+ } else return this.showContainer(id, intent, instanceOrigin);
2997
3173
  }
2998
3174
 
2999
3175
  onCloseContainer() {
@@ -3046,7 +3222,7 @@ class EstreComponent extends EstrePageHostHandle {
3046
3222
  else return false;
3047
3223
  }
3048
3224
 
3049
- close(isRequest = true, isTermination = false) {
3225
+ close(isRequest = true, isTermination = !this.isStatic) {
3050
3226
  if (isRequest) {
3051
3227
  if (this.isModal) {
3052
3228
  return this.onTop ? estreUi.closeModalTab(this.id, this.$host) : false;
@@ -3115,8 +3291,8 @@ class EstreMenuComponent extends EstreComponent {
3115
3291
 
3116
3292
 
3117
3293
 
3118
- constructor(component) {
3119
- super(component);
3294
+ constructor(component, instanceOrigin) {
3295
+ super(component, instanceOrigin);
3120
3296
  }
3121
3297
 
3122
3298
  release(remove) {
@@ -3149,9 +3325,9 @@ class EstreMenuComponent extends EstreComponent {
3149
3325
  } else super.show(false, setFocus);
3150
3326
  }
3151
3327
 
3152
- close(isRequest = true, isTermination = false) {
3328
+ close(isRequest = true, isTermination = !this.isStatic) {
3153
3329
  if (isRequest) {
3154
- return estreUi.closeMenuArea(this.id, isTermination);
3330
+ return estreUi.closeMenuArea(this.id, this.instanceOrigin, isTermination);
3155
3331
  } else return super.close(false, isTermination);
3156
3332
  }
3157
3333
  }
@@ -3179,8 +3355,8 @@ class EstreHeaderComponent extends EstreComponent {
3179
3355
 
3180
3356
 
3181
3357
 
3182
- constructor(component) {
3183
- super(component);
3358
+ constructor(component, instanceOrigin) {
3359
+ super(component, instanceOrigin);
3184
3360
  }
3185
3361
 
3186
3362
  release(remove) {
@@ -3213,9 +3389,9 @@ class EstreHeaderComponent extends EstreComponent {
3213
3389
  } else super.show(false, setFocus);
3214
3390
  }
3215
3391
 
3216
- close(isRequest = true, isTermination = false) {
3392
+ close(isRequest = true, isTermination = !this.isStatic) {
3217
3393
  if (isRequest) {
3218
- return estreUi.closeHeaderBar(this.id, isTermination);
3394
+ return estreUi.closeHeaderBar(this.id, this.instanceOrigin, isTermination);
3219
3395
  } else return super.close(false, isTermination);
3220
3396
  }
3221
3397
  }
@@ -3243,8 +3419,8 @@ class EstreInstantComponent extends EstreComponent {
3243
3419
 
3244
3420
 
3245
3421
 
3246
- constructor(component) {
3247
- super(component);
3422
+ constructor(component, instanceOrigin) {
3423
+ super(component, instanceOrigin);
3248
3424
  }
3249
3425
 
3250
3426
  release(remove) {
@@ -3277,9 +3453,9 @@ class EstreInstantComponent extends EstreComponent {
3277
3453
  } else super.show(false, setFocus);
3278
3454
  }
3279
3455
 
3280
- close(isRequest = true, isTermination = false) {
3456
+ close(isRequest = true, isTermination = !this.isStatic) {
3281
3457
  if (isRequest) {
3282
- return estreUi.closeInstantBlinded(this.id, isTermination);
3458
+ return estreUi.closeInstantBlinded(this.id, this.instanceOrigin, isTermination);
3283
3459
  } else return super.close(false, isTermination);
3284
3460
  }
3285
3461
  }
@@ -3307,8 +3483,8 @@ class EstreOverlayComponent extends EstreInstantComponent {
3307
3483
 
3308
3484
 
3309
3485
 
3310
- constructor(component) {
3311
- super(component);
3486
+ constructor(component, instanceOrigin) {
3487
+ super(component, instanceOrigin);
3312
3488
  }
3313
3489
 
3314
3490
  release(remove) {
@@ -3341,9 +3517,9 @@ class EstreOverlayComponent extends EstreInstantComponent {
3341
3517
  } else super.show(false, setFocus);
3342
3518
  }
3343
3519
 
3344
- close(isRequest = true, isTermination = false) {
3520
+ close(isRequest = true, isTermination = !this.isStatic) {
3345
3521
  if (isRequest) {
3346
- return estreUi.closeManagedOverlay(this.id, isTermination);
3522
+ return estreUi.closeManagedOverlay(this.id, this.instanceOrigin, isTermination);
3347
3523
  } else return super.close(false, isTermination);
3348
3524
  }
3349
3525
  }
@@ -3418,8 +3594,8 @@ class EstreContainer extends EstrePageHostHandle {
3418
3594
  }
3419
3595
  get stepPagesLength() { return pageManager.getStepPagesLength(this.#articleStepsId, this.id, this.component.id, this.component.sectionBound); }
3420
3596
 
3421
- constructor(container, component) {
3422
- super(container);
3597
+ constructor(container, component, instanceOrigin) {
3598
+ super(container, instanceOrigin);
3423
3599
  this.component = component;
3424
3600
  this.id = this.$host.attr(eds.containerId);
3425
3601
  }
@@ -3499,8 +3675,8 @@ class EstreContainer extends EstrePageHostHandle {
3499
3675
  return this.initArticles(intent);
3500
3676
  }
3501
3677
 
3502
- registerSubPage(element, intent) {
3503
- return this.registerArticle(element, intent);
3678
+ registerSubPage(element, intent, instanceOrigin) {
3679
+ return this.registerArticle(element, intent, instanceOrigin);
3504
3680
  }
3505
3681
 
3506
3682
  unregisterConatiner(pageHandle) {
@@ -3551,11 +3727,12 @@ class EstreContainer extends EstrePageHostHandle {
3551
3727
  }
3552
3728
  }
3553
3729
 
3554
- registerArticle(element, intent) {
3730
+ registerArticle(element, intent, instanceOrigin) {
3555
3731
  this.unregisterArticle(element.pageHandle);
3556
- const article = new EstreArticle(element, this);
3557
- this.$article[article.id] = article.$host;
3558
- this.articles[article.id] = article;
3732
+ const article = new EstreArticle(element, this, instanceOrigin);
3733
+ const instanceId = article.instanceId;
3734
+ this.$article[instanceId] = article.$host;
3735
+ this.articles[instanceId] = article;
3559
3736
  this.articleList.push(article);
3560
3737
  const registered = EstreUiPage.registerOrCommitFrom(article);
3561
3738
  article.init(registered, intent);
@@ -3565,10 +3742,11 @@ class EstreContainer extends EstrePageHostHandle {
3565
3742
 
3566
3743
  unregisterArticle(article) {
3567
3744
  if (article == null) return;
3745
+ const instanceId = article.instanceId;
3568
3746
  const unregistered = EstreUiPage.unregisterFrom(article);
3569
3747
  article.release(!article.isStatic ? true : null);
3570
- if (this.$article[article.id] != null) delete this.$article[article.id];
3571
- if (this.articles[article.id] != null) delete this.articles[article.id];
3748
+ if (this.$article[instanceId] != null) delete this.$article[instanceId];
3749
+ if (this.articles[instanceId] != null) delete this.articles[instanceId];
3572
3750
  const index = this.articleList.indexOf(article);
3573
3751
  if (index > -1) this.articleList.splice(index, 1);
3574
3752
  return unregistered;
@@ -3702,7 +3880,7 @@ class EstreContainer extends EstrePageHostHandle {
3702
3880
 
3703
3881
  close(isRequest = true, isTermination = false) {
3704
3882
  if (isRequest) {
3705
- return this.component.closeContainer(this.id, isTermination) ?? super.close(isTermination);
3883
+ return this.component.closeContainer(this.id, this.instanceOrigin, isTermination) ?? super.close(isTermination);
3706
3884
  } else return super.close(isTermination);
3707
3885
  }
3708
3886
 
@@ -3744,7 +3922,7 @@ class EstreContainer extends EstrePageHostHandle {
3744
3922
 
3745
3923
  if (stepped.length > 0) {
3746
3924
  const sorted = stepped.sort();
3747
- for (var i=sorted.length-1; i>-1; i--) closer.push(this.closeArticle(sorted[i], isTermination));
3925
+ for (var i=sorted.length-1; i>-1; i--) closer.push(this.closeArticle(sorted[i], u, isTermination));
3748
3926
  } else {
3749
3927
  for (var article of this.articleList.reverse()) closer.push(article.close(true, isTermination));
3750
3928
  }
@@ -3756,32 +3934,31 @@ class EstreContainer extends EstrePageHostHandle {
3756
3934
 
3757
3935
 
3758
3936
  // handles
3759
- showSubPage(id, intent) {
3760
- return this.showArticle(id, intent);
3937
+ showSubPage(id, intent, instanceOrigin) {
3938
+ return this.showArticle(id, intent, instanceOrigin);
3761
3939
  }
3762
3940
 
3763
- openSubPage(id, intent) {
3764
- return this.openArticle(id, intent);
3941
+ openSubPage(id, intent, instanceOrigin) {
3942
+ return this.openArticle(id, intent, instanceOrigin);
3765
3943
  }
3766
3944
 
3767
3945
  bringSubPage(id, intent) {
3768
- return this.bringArticle(id, intent);
3946
+ return this.bringArticle(id, intent, instanceOrigin);
3769
3947
  }
3770
3948
 
3771
- closeSubPage(id, isTermination = false) {
3772
- return this.closeArticle(id, isTermination);
3949
+ closeSubPage(id, instanceOrigin, isTermination = false) {
3950
+ return this.closeArticle(id, instanceOrigin, isTermination);
3773
3951
  }
3774
3952
 
3775
- showArticle(id, intent) {
3953
+ showArticle(id, intent, instanceOrigin) {
3776
3954
  if (id != null && !this.isClosing) {
3777
- const $target = this.$article[id];
3778
- if ($target != null && $target.length > 0) {
3955
+ const show = $target => {
3779
3956
  const onlyOne = this.$articles.filter(ntc("dummy")).length === 1;
3780
3957
  const $currentTop = this.$articles.filter(asv(eds.onTop, t1));
3781
3958
  //console.log("current top: ", $currentTop);
3782
3959
  const currentTopHandle = this.currentTop;
3783
3960
  const currentTopHandleId = currentTopHandle.id;
3784
- if (id != currentTopHandleId && currentTopHandleId != this.prevSubPageId) {
3961
+ if (id != currentTopHandleId && currentTopHandleId != this.latestSubPageId) {
3785
3962
  this.prevSubPageId = currentTopHandleId;
3786
3963
 
3787
3964
  // if (estreUi.euiState == "onReady" && currentTopHandle != null) estreUi.pushCurrentState(currentTopHandle);
@@ -3853,23 +4030,36 @@ class EstreContainer extends EstrePageHostHandle {
3853
4030
  }
3854
4031
  return true;
3855
4032
  }
4033
+ };
4034
+
4035
+ const $target = this.$article[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
4036
+ if ($target != null && $target.length > 0) return show($target);
4037
+ else if (instanceOrigin == n) {
4038
+ const articleIds = this.$article.ways.filter(it => it.startsWith(id + "^"));
4039
+ if (articleIds.length > 0) {
4040
+ const articleId = articleIds[articleIds.length - 1];
4041
+ const $target = this.$article[articleId];
4042
+ if ($target != null && $target.length > 0) return show($target);
4043
+ }
3856
4044
  }
3857
4045
  }
3858
4046
  return false;
3859
4047
  }
3860
4048
 
3861
- openArticle(id, intent) {
4049
+ openArticle(id, intent, instanceOrigin) {
3862
4050
  if (this.isClosing) return false;
3863
4051
  const page = pageManager.getArticle(id, this.id, this.component.id, this.component.sectionBound);
3864
4052
  if (page == null) return null;
3865
4053
  if (page.statement == "static") return null;
3866
- var $exist = this.$articles.filter(aiv(eds.articleId, id));
3867
- if ($exist.length > 0) {
3868
- this.closeArticle(id);
4054
+ if (!page.isMultiInstance) {
3869
4055
  var $exist = this.$articles.filter(aiv(eds.articleId, id));
3870
4056
  if ($exist.length > 0) {
3871
- if ($exist[0].pageHandle != null) $exist[0].pageHandle.release(true);
3872
- else $exist.remove();
4057
+ this.closeArticle(id);
4058
+ var $exist = this.$articles.filter(aiv(eds.articleId, id));
4059
+ if ($exist.length > 0) {
4060
+ if ($exist[0].pageHandle != null) $exist[0].pageHandle.release(true);
4061
+ else $exist.remove();
4062
+ }
3873
4063
  }
3874
4064
  }
3875
4065
  const $articles = this.$articles;
@@ -3878,22 +4068,21 @@ class EstreContainer extends EstrePageHostHandle {
3878
4068
  else this.$host.append(page.live);
3879
4069
  const $article = this.$articles.filter(aiv(eds.articleId, id));
3880
4070
  if ($article == null || $article.length < 1) return null;
3881
- const article = this.registerArticle($article[0], intent);
4071
+ const article = this.registerArticle($article[$article.length - 1], intent, instanceOrigin);
3882
4072
  //this.#updateStepNavigation();
3883
4073
  return article;
3884
4074
  }
3885
4075
 
3886
- bringArticle(id, intent) {
4076
+ bringArticle(id, intent, instanceOrigin) {
3887
4077
  if (this.articles[id] == null) {
3888
- if (this.openArticle(id, intent)) return this.showArticle(id);
4078
+ if (this.openArticle(id, intent, instanceOrigin)) return this.showArticle(id);
3889
4079
  else return false;
3890
4080
  } else return this.showArticle(id, intent);
3891
4081
  }
3892
4082
 
3893
- closeArticle(id, isTermination = false) {
4083
+ closeArticle(id, instanceOrigin, isTermination = false) {
3894
4084
  if (id != null) {
3895
- const article = this.articles[id];
3896
- if (article != null) {
4085
+ const close = article => {
3897
4086
  const task = article.close(false, isTermination || !article.isStatic);
3898
4087
  if (!isTermination && !this.isClosing) postAsyncQueue(async _ => {
3899
4088
  if (this.isClosing) return;
@@ -3901,9 +4090,8 @@ class EstreContainer extends EstrePageHostHandle {
3901
4090
  const subPageList = this.subPageList.filter(it => !it.isClosing && it != target);
3902
4091
  if (subPageList.length > 0) {
3903
4092
  const prev = this.prevSubPageId;
3904
- if (prev != null && id != prev && this.subPages[prev] != null) {
3905
- if (this.showSubPage(prev)) this.prevSubPageId = null;
3906
- } else subPageList[subPageList.length - 1].show();
4093
+ if (prev != null) this.showSubPage(prev);
4094
+ else subPageList[subPageList.length - 1].show();
3907
4095
  } else {
3908
4096
  await task;
3909
4097
  if (!this.isClosing && !this.isStatic && subPageList.length < 1) this.close(true, true);
@@ -3914,6 +4102,17 @@ class EstreContainer extends EstrePageHostHandle {
3914
4102
  if (isTermination || !article.isStatic) this.unregisterArticle(article);
3915
4103
  return result;
3916
4104
  });
4105
+ };
4106
+
4107
+ const article = this.articles[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
4108
+ if (article != null) return close(article);
4109
+ else if (instanceOrigin == n) {
4110
+ const articleIds = this.$article.ways.filter(it => it.startsWith(id + "^"));
4111
+ if (articleIds.length > 0) {
4112
+ const articleId = articleIds[articleIds.length - 1];
4113
+ const article = this.articles[articleId];
4114
+ return close(article);
4115
+ }
3917
4116
  }
3918
4117
  }
3919
4118
  return null;
@@ -3959,8 +4158,8 @@ class EstreArticle extends EstrePageHandle {
3959
4158
 
3960
4159
  dateShowers = [];
3961
4160
 
3962
- constructor(article, container) {
3963
- super(article);
4161
+ constructor(article, container, instanceOrigin) {
4162
+ super(article, instanceOrigin);
3964
4163
  this.container = container;
3965
4164
  this.id = this.$host.attr(eds.articleId);
3966
4165
  }
@@ -4005,7 +4204,7 @@ class EstreArticle extends EstrePageHandle {
4005
4204
 
4006
4205
  close(isRequest = true, isTermination = false) {
4007
4206
  if (isRequest) {
4008
- return this.container.closeArticle(this.id, isTermination) ?? super.close(isTermination);
4207
+ return this.container.closeArticle(this.id, this.instanceOrigin, isTermination) ?? super.close(isTermination);
4009
4208
  } else return super.close(isTermination);
4010
4209
  }
4011
4210
 
@@ -4458,11 +4657,11 @@ class EstreSelectionDialogPageHandler extends EstreDialogPageHandler {
4458
4657
  if (isNotNully(defaultSelected)) forkv(defaultSelected, (k, v) => {
4459
4658
  switch(to(v)) {
4460
4659
  case BOOLEAN:
4461
- this.$optionCheckboxes.filter(aiv("data-index", k)).prop(m.v, v);
4660
+ this.$optionCheckboxes.filter(aiv(eds.index, k)).prop(m.v, v);
4462
4661
  break;
4463
4662
 
4464
4663
  case NUMBER:
4465
- this.$optionCheckboxes.filter(aiv("data-index", v)).prop(m.v, true);
4664
+ this.$optionCheckboxes.filter(aiv(eds.index, v)).prop(m.v, true);
4466
4665
  break;
4467
4666
  }
4468
4667
  });
@@ -4535,6 +4734,72 @@ class EstreSelectionDialogPageHandler extends EstreDialogPageHandler {
4535
4734
  }
4536
4735
  }
4537
4736
 
4737
+ class EstreDialsDialogPageHandler extends EstreDialogPageHandler {
4738
+ $dial;
4739
+ dialHandle;
4740
+
4741
+ $confirm;
4742
+ $another;
4743
+
4744
+ onBring(handle) {
4745
+ super.onBring(handle);
4746
+
4747
+ this.$dial = handle.$host.find(uis.multiDialSlot);
4748
+
4749
+ this.$confirm = this.$actions.find(btn + cls + "confirm");
4750
+ this.$another = this.$actions.find(btn + cls + "another");
4751
+ }
4752
+
4753
+ onOpen(handle) {
4754
+ super.onOpen(handle);
4755
+
4756
+ this.intent.handle = this.dialHandle = this.$dial[0].handle;
4757
+
4758
+ handle.intent?.onSelect?.let(it => this.dialHandle.setOnSelected(it));
4759
+
4760
+ handle.intent?.data?.let(it => {
4761
+ this.$dial.css("--font-size", it.fontSize ?? "2rem");
4762
+ if (it.fontWeight != n) this.$dial.css("--font-weight", it.fontWeight);
4763
+ this.$dial.css("--item-height", it.itemHeight ?? "1.2em");
4764
+ this.$dial.css("--holder-pad", it.holderPad ?? "var(--basic-ui-inset-h)");
4765
+ if (it.holderPadL != n) this.$dial.css("--holder-pad-l", it.holderPadL);
4766
+ if (it.holderPadR != n) this.$dial.css("--holder-pad-r", it.holderPadR);
4767
+ if (it.colGap != n) this.$dial.css("--col-gap", it.colGap);
4768
+ if (it.boundGap != n) this.$dial.css("--bound-gap", it.boundGap);
4769
+ });
4770
+
4771
+ const handler = this;
4772
+
4773
+ this.$confirm.click(function (e) {
4774
+ e.preventDefault();
4775
+ e.stopPropagation();
4776
+ const { itemSelectionIndexes, itemSelectionValues } = handler.dialHandle;
4777
+ handle?.intent?.onConfirm?.(itemSelectionIndexes.mock, itemSelectionValues.mock, handle.intent?.data?.initial);
4778
+ handle?.close();
4779
+ return false;
4780
+ });
4781
+ if (handle?.intent?.data?.callbackAnother == null) this.$another.remove();
4782
+ else this.$another.click(function (e) {
4783
+ e.preventDefault();
4784
+ e.stopPropagation();
4785
+ const { itemSelectionIndexes, itemSelectionValues } = handler.dialHandle;
4786
+ handle?.intent?.onAnother?.(itemSelectionIndexes.mock, itemSelectionValues.mock, handle.intent?.data?.initial);
4787
+ handle?.close();
4788
+ return false;
4789
+ });
4790
+
4791
+ this.$confirm.focus();
4792
+ }
4793
+
4794
+ onFocus(handle) {
4795
+ this.$confirm.focus();
4796
+ }
4797
+
4798
+ onClose(handle) {
4799
+ const { itemSelectionIndexes, itemSelectionValues } = this.dialHandle;
4800
+ handle?.intent?.onDissmiss(handle.intent?.data?.initial, itemSelectionIndexes.mock, itemSelectionValues.mock);
4801
+ }
4802
+ }
4538
4803
 
4539
4804
  /**
4540
4805
  * Pages profiling manager
@@ -4748,6 +5013,9 @@ class EstreUiPage {
4748
5013
  },
4749
5014
  "$i&o=toastUpSlide#selection^": class extends EstreSelectionDialogPageHandler {
4750
5015
 
5016
+ },
5017
+ "$i&o=toastUpSlide#dials^": class extends EstreDialsDialogPageHandler {
5018
+
4751
5019
  },
4752
5020
 
4753
5021
  "$i&o=interaction#onRunning^": class extends EstreLottieAnimatedHandler {
@@ -4760,11 +5028,11 @@ class EstreUiPage {
4760
5028
  } else if (backHolds < cancellationExceeds - 1) {
4761
5029
  return onBackWhile(handle);
4762
5030
  } else if (backHolds == cancellationExceeds - 1) {
4763
- const instanceOrigin = latestIO;
5031
+ // const instanceOrigin = latestIO;
4764
5032
  backHolds = 0;
4765
5033
  this.isTriggeredCancellation = t;
4766
5034
  this.intentData?.callbackCancellation?.();
4767
- postQueue(_ => go(instanceOrigin));
5035
+ // postQueue(_ => go(instanceOrigin));
4768
5036
  return handle.close();
4769
5037
  }
4770
5038
  }
@@ -5068,6 +5336,25 @@ class EstreUiPage {
5068
5336
  else return null;
5069
5337
  }
5070
5338
 
5339
+ #componentInstanceOrigin;
5340
+ #containerInstanceOrigin;
5341
+ #articleInstanceOrigin;
5342
+
5343
+ get componentInstanceOrigin() { return this.#componentInstanceOrigin; }
5344
+ get containerInstanceOrigin() { return this.#containerInstanceOrigin; }
5345
+ get articleInstanceOrigin() { return this.#articleInstanceOrigin; }
5346
+
5347
+ get instanceOrigin() {
5348
+ if (this.#article != null) return this.#articleInstanceOrigin;
5349
+ else if (this.#container != null) return this.#containerInstanceOrigin;
5350
+ else if (this.#component != null) return this.#componentInstanceOrigin;
5351
+ else return null;
5352
+ }
5353
+
5354
+ get componentInstanceId() { return this.#componentIsMultiInstance ? this.#component + "^" + this.#componentInstanceOrigin : this.component; }
5355
+ get containerInstanceId() { return this.#containerIsMultiInstance ? this.#container + "^" + this.#containerInstanceOrigin : this.container; }
5356
+ get articleInstanceId() { return this.#articleIsMultiInstance ? this.#article + "^" + this.#articleInstanceOrigin : this.article; }
5357
+
5071
5358
  #instances = [];
5072
5359
  get instances() { return this.#instances; }
5073
5360
 
@@ -5122,9 +5409,26 @@ class EstreUiPage {
5122
5409
  pid += "&" + (this.sectionBound == "main" ? "m" : (this.sectionBound == "blind" ? "b" : (this.sectionBound == "overlay" ? "o" : (this.sectionBound == "header" ? "h" : (this.sectionBound == "menu" ? "u" : "")))));
5123
5410
  pid += "=";
5124
5411
  pid += this.#component;
5125
- if (this.#container != null) pid += "#" + this.#container;
5126
- if (this.#article != null) pid += "@" + this.#article;
5127
- if (this.isMultiInstance) pid += "^";
5412
+ if (this.#componentIsMultiInstance) pid += "^";
5413
+ if (this.#container != null) {
5414
+ pid += "#" + this.#container;
5415
+ if (this.#containerIsMultiInstance) pid += "^";
5416
+ }
5417
+ if (this.#article != null) {
5418
+ pid += "@" + this.#article;
5419
+ if (this.#articleIsMultiInstance) pid += "^";
5420
+ }
5421
+ return pid;
5422
+ }
5423
+
5424
+ get instancePid() {
5425
+ var pid = "";
5426
+ pid += "$" + (this.statement == "static" ? "s" : (this.statement == "instant" ? "i" : ""));
5427
+ pid += "&" + (this.sectionBound == "main" ? "m" : (this.sectionBound == "blind" ? "b" : (this.sectionBound == "overlay" ? "o" : (this.sectionBound == "header" ? "h" : (this.sectionBound == "menu" ? "u" : "")))));
5428
+ pid += "=";
5429
+ pid += this.componentInstanceId;
5430
+ if (this.#container != null) pid += "#" + this.containerInstanceId;
5431
+ if (this.#article != null) pid += "@" + this.articleInstanceId;
5128
5432
  return pid;
5129
5433
  }
5130
5434
 
@@ -5227,6 +5531,18 @@ class EstreUiPage {
5227
5531
  return this;
5228
5532
  }
5229
5533
 
5534
+ setInstanceOrigin(instanceOrigin) {
5535
+ if (isArray(instanceOrigin)) {
5536
+ this.#componentInstanceOrigin = instanceOrigin[0];
5537
+ this.#containerInstanceOrigin = instanceOrigin[1];
5538
+ this.#articleInstanceOrigin = instanceOrigin[2];
5539
+ } else equalCase(this.hostType, {
5540
+ "component": _ => this.#componentInstanceOrigin = instanceOrigin,
5541
+ "container": _ => this.#containerInstanceOrigin = instanceOrigin,
5542
+ "article": _ => this.#articleInstanceOrigin = instanceOrigin,
5543
+ });
5544
+ }
5545
+
5230
5546
  setComponentRefer($component) {
5231
5547
  if (this.#commited) return false;
5232
5548
 
@@ -5239,6 +5555,7 @@ class EstreUiPage {
5239
5555
 
5240
5556
  this.#componentStatement = $component.attr(eds.static) == t1 ? "static" : "instant";
5241
5557
  this.#componentIsMultiInstance = $component.attr(eds.multiInstance) == t1;
5558
+ this.#componentInstanceOrigin = $component.attr(eds.instanceOrigin)?.ifEmpty(_ => u);
5242
5559
 
5243
5560
  if (this.#sectionBound == null) {
5244
5561
  const $componentHost = $component.closest("main, nav, header, footer");
@@ -5264,6 +5581,7 @@ class EstreUiPage {
5264
5581
 
5265
5582
  this.#containerStatement = $container.attr(eds.static) == t1 ? "static" : "instant";
5266
5583
  this.#containerIsMultiInstance = $container.attr(eds.multiInstance) == t1;
5584
+ this.#containerInstanceOrigin = $container.attr(eds.instanceOrigin)?.ifEmpty(_ => u);
5267
5585
 
5268
5586
  if ($component == null) $component = $container.closest("section");
5269
5587
 
@@ -5286,6 +5604,7 @@ class EstreUiPage {
5286
5604
 
5287
5605
  this.#articleStatement = $article.attr(eds.static) == t1 ? "static" : "instant";
5288
5606
  this.#articleIsMultiInstance = $article.attr(eds.multiInstance) == t1;
5607
+ this.#articleInstanceOrigin = $article.attr(eds.instanceOrigin)?.ifEmpty(_ => u);
5289
5608
 
5290
5609
  if ($container == null) $container = $article.closest("div.container");
5291
5610
 
@@ -5402,6 +5721,7 @@ class EstreUiPageManager {
5402
5721
  get toastPrompt() { return "$i&o=toastUpSlide#prompt^"; },
5403
5722
  get toastOption() { return "$i&o=toastUpSlide#option^"; },
5404
5723
  get toastSelection() { return "$i&o=toastUpSlide#selection^"; },
5724
+ get toastDials() { return "$i&o=toastUpSlide#dials^"; },
5405
5725
 
5406
5726
 
5407
5727
  get onRunning() { return "$i&o=interaction#onRunning^"; },
@@ -5491,6 +5811,7 @@ class EstreUiPageManager {
5491
5811
  if (pid.indexOf("$") < 0) pid = this.findPid(pid);
5492
5812
  const page = this.get(pid);
5493
5813
  if (page == null) return null;
5814
+ page.setInstanceOrigin(instanceOrigin);
5494
5815
  const sections = page.sections;
5495
5816
  if (sections == null) return null;
5496
5817
 
@@ -5498,35 +5819,38 @@ class EstreUiPageManager {
5498
5819
 
5499
5820
  //check open component
5500
5821
  const isIntentNone = typeof intent == UNDEFINED;
5822
+ const componentInstanceOrigin = page.componentInstanceOrigin;
5501
5823
  var componentIntentPushed = false;
5502
- var component = sections[page.component];
5824
+ var component = sections[page.componentInstanceId];
5503
5825
  var existComponent = false;
5504
5826
  if (component == null) {
5505
5827
  if (page.componentIsInatant) {
5506
5828
  if (page.isMenu) {
5507
5829
  if (page.isComponent) {
5508
- component = estreUi.openMenuArea(page.component, intent);
5830
+ component = estreUi.openMenuArea(page.component, intent, componentInstanceOrigin);
5509
5831
  componentIntentPushed = true;
5510
- } else component = estreUi.openMenuArea(page.component);
5832
+ } else component = estreUi.openMenuArea(page.component, u, componentInstanceOrigin);
5511
5833
  } else if (page.isBlinded) {
5512
5834
  if (page.isComponent) {
5513
- component = estreUi.openInstantBlinded(page.component, intent);
5835
+ component = estreUi.openInstantBlinded(page.component, intent, componentInstanceOrigin);
5514
5836
  componentIntentPushed = true;
5515
- } else component = estreUi.openInstantBlinded(page.component);
5837
+ } else component = estreUi.openInstantBlinded(page.component, u, componentInstanceOrigin);
5516
5838
  } else if (page.isOverlay) {
5517
5839
  if (page.isComponent) {
5518
- component = estreUi.openManagedOverlay(page.component, intent);
5840
+ component = estreUi.openManagedOverlay(page.component, intent, componentInstanceOrigin);
5519
5841
  componentIntentPushed = true;
5520
- } else component = estreUi.openManagedOverlay(page.component);
5842
+ } else component = estreUi.openManagedOverlay(page.component, u, componentInstanceOrigin);
5521
5843
  } else if (page.isHeader) {
5522
5844
  if (page.isComponent) {
5523
- component = estreUi.openHeaderBar(page.component, intent);
5845
+ component = estreUi.openHeaderBar(page.component, intent, componentInstanceOrigin);
5524
5846
  componentIntentPushed = true;
5525
- } else component = estreUi.openHeaderBar(page.component);
5847
+ } else component = estreUi.openHeaderBar(page.component, u, componentInstanceOrigin);
5526
5848
  } else return false;
5527
5849
  } else return false;
5528
5850
  } else existComponent = true;
5529
5851
  if (component == null) return null;
5852
+ const containerInstanceOrigin = page.containerInstanceOrigin;
5853
+ const articleInstanceOrigin = page.articleInstanceOrigin;
5530
5854
  var containerIntentPushed = false;
5531
5855
  var articleIntentPushed = false;
5532
5856
  var container = null;
@@ -5535,13 +5859,13 @@ class EstreUiPageManager {
5535
5859
  var existArticle = false;
5536
5860
  if (page.container != null) {
5537
5861
  //check open container
5538
- container = component.containers[page.container];
5862
+ container = component.containers[page.containerInstanceId];
5539
5863
  if (container == null) {
5540
5864
  if (page.containerIsInatant) {
5541
5865
  if (page.isArticle || page.isContainer || page.container == "root") {
5542
- container = component.openContainer(page.container, intent);
5866
+ container = component.openContainer(page.container, intent, containerInstanceOrigin);
5543
5867
  containerIntentPushed = true;
5544
- } else container = component.openContainer(page.container);
5868
+ } else container = component.openContainer(page.container, u, containerInstanceOrigin);
5545
5869
  } else if (page.isContainer) return false;//static container is cannot open
5546
5870
  else {
5547
5871
 
@@ -5551,13 +5875,13 @@ class EstreUiPageManager {
5551
5875
 
5552
5876
  if (page.article != null) {
5553
5877
  //check open article
5554
- article = container.articles[page.article];
5878
+ article = container.articles[page.articleInstanceId];
5555
5879
  if (article == null) {
5556
5880
  if (page.articleIsInatant) {
5557
5881
  if (page.isArticle || page.article == "main") {
5558
- article = container.openArticle(page.article, intent);
5882
+ article = container.openArticle(page.article, intent, articleInstanceOrigin);
5559
5883
  articleIntentPushed = true;
5560
- } else article = container.openArticle(page.article);
5884
+ } else article = container.openArticle(page.article, u, articleInstanceOrigin);
5561
5885
  } else return false;//static article is cannot open
5562
5886
  } else existArticle = true;
5563
5887
  if (article == null) return null;
@@ -5568,35 +5892,35 @@ class EstreUiPageManager {
5568
5892
  const isRootMain = page.container == "root" && page.article == "main";
5569
5893
  switch (page.hostType) {
5570
5894
  case "article":
5571
- if (!isIntentNone && existArticle && (page.isArticle || page.article == "main")) targetProcessed.article = container.showArticle(page.article, intent);
5895
+ if (!isIntentNone && existArticle && (page.isArticle || page.article == "main")) targetProcessed.article = container.showArticle(page.article, intent, articleInstanceOrigin);
5572
5896
  else targetProcessed.article = article.show();
5573
5897
  success = targetProcessed.article;
5574
5898
  case "container":
5575
5899
  if (success) {
5576
- if (!isIntentNone && existContainer && (page.isContainer || isRootMain)) targetProcessed.container = component.showContainer(page.container, intent);
5900
+ if (!isIntentNone && existContainer && (page.isContainer || isRootMain)) targetProcessed.container = component.showContainer(page.container, intent, containerInstanceOrigin);
5577
5901
  else targetProcessed.container = container.show();
5578
5902
  success = targetProcessed.container;
5579
5903
  }
5580
5904
  case "component":
5581
5905
  if (success) {
5582
5906
  if (page.isHeader) {
5583
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showHeaderBar(page.component, intent);
5584
- else targetProcessed.component = estreUi.showHeaderBar(page.component);
5907
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showHeaderBar(page.component, intent, componentInstanceOrigin);
5908
+ else targetProcessed.component = estreUi.showHeaderBar(page.component, u, componentInstanceOrigin);
5585
5909
  } else if (page.isMenu) {
5586
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showMenuArea(page.component, intent);
5587
- else targetProcessed.component = estreUi.showMenuArea(page.component);
5910
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showMenuArea(page.component, intent, componentInstanceOrigin);
5911
+ else targetProcessed.component = estreUi.showMenuArea(page.component, u, componentInstanceOrigin);
5588
5912
  } else if (page.isOverlay) {
5589
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showManagedOverlay(page.component, intent);
5590
- else targetProcessed.component = estreUi.showManagedOverlay(page.component);
5913
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showManagedOverlay(page.component, intent, componentInstanceOrigin);
5914
+ else targetProcessed.component = estreUi.showManagedOverlay(page.component, u, componentInstanceOrigin);
5591
5915
  } else if (page.isBlinded) {
5592
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showInstantBlinded(page.component, intent);
5593
- else targetProcessed.component = estreUi.showInstantBlinded(page.component);
5916
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showInstantBlinded(page.component, intent, componentInstanceOrigin);
5917
+ else targetProcessed.component = estreUi.showInstantBlinded(page.component, u, componentInstanceOrigin);
5594
5918
  } else if (component.isModal) {
5595
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.openModalTab(page.component, component, intent);
5596
- else targetProcessed.component = estreUi.openModalTab(page.component, component);
5919
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.openModalTab(page.component, component, intent, componentInstanceOrigin);
5920
+ else targetProcessed.component = estreUi.openModalTab(page.component, u, componentInstanceOrigin);
5597
5921
  } else {
5598
- if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.switchRootTab(page.component, intent);
5599
- else targetProcessed.component = estreUi.mainCurrentOnTop == component || estreUi.switchRootTab(page.component);
5922
+ if (!isIntentNone && existComponent && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.switchRootTab(page.component, intent, componentInstanceOrigin);
5923
+ else targetProcessed.component = estreUi.mainCurrentOnTop == component || estreUi.switchRootTab(page.component, u, componentInstanceOrigin);
5600
5924
  }
5601
5925
  success = targetProcessed.component;
5602
5926
  }
@@ -5613,21 +5937,25 @@ class EstreUiPageManager {
5613
5937
  if (pid.indexOf("$") < 0) pid = this.findPid(pid);
5614
5938
  const page = this.get(pid);
5615
5939
  if (page == null) return null;
5940
+ page.setInstanceOrigin(instanceOrigin);
5616
5941
  const sections = page.sections;
5617
5942
  if (sections == null) return null;
5618
5943
 
5619
5944
  if (intent?.bringOnBack != n && intent.bringOnBack.hostType == n) intent.bringOnBack.hostType = page.hostType;
5620
5945
 
5621
5946
  const isIntentNone = typeof intent == UNDEFINED;
5622
- var component = sections[page.component];
5947
+ var component = sections[page.componentInstanceId];
5623
5948
  if (component == null) return null;
5949
+ const componentInstanceOrigin = page.componentInstanceOrigin;
5950
+ const containerInstanceOrigin = page.containerInstanceOrigin;
5951
+ const articleInstanceOrigin = page.articleInstanceOrigin;
5624
5952
  var container = null;
5625
5953
  var article = null;
5626
5954
  if (page.container != null) {
5627
- container = component.containers[page.container];
5955
+ container = component.containers[page.containerInstanceId];
5628
5956
  if (container == null) return null;
5629
5957
  if (page.article != null) {
5630
- article = container.articles[page.article];
5958
+ article = container.articles[page.articleInstanceId];
5631
5959
  if (article == null) return null;
5632
5960
  }
5633
5961
  }
@@ -5635,12 +5963,12 @@ class EstreUiPageManager {
5635
5963
  var targetProcessed = { component: null, container: null, article: null };
5636
5964
  switch (page.hostType) {
5637
5965
  case "article":
5638
- if (!isIntentNone && (page.isArticle || page.article == "main")) targetProcessed.article = container.showArticle(page.article, intent);
5966
+ if (!isIntentNone && (page.isArticle || page.article == "main")) targetProcessed.article = container.showArticle(page.article, intent, articleInstanceOrigin);
5639
5967
  else targetProcessed.article = article.show();
5640
5968
  success = targetProcessed.article;
5641
5969
  case "container":
5642
5970
  if (success) {
5643
- if (!isIntentNone && (page.isContainer || (page.article == "main" && page.container == "root"))) targetProcessed.container = component.showContainer(page.container, intent);
5971
+ if (!isIntentNone && (page.isContainer || (page.article == "main" && page.container == "root"))) targetProcessed.container = component.showContainer(page.container, intent, containerInstanceOrigin);
5644
5972
  else targetProcessed.container = container.show();
5645
5973
  success = targetProcessed.container;
5646
5974
  }
@@ -5648,20 +5976,20 @@ class EstreUiPageManager {
5648
5976
  if (success) {
5649
5977
  const isRootMain = page.container == "root" && page.article == "main";
5650
5978
  if (page.isOverlay) {
5651
- if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showManagedOverlay(page.component, intent);
5652
- else targetProcessed.component = estreUi.showManagedOverlay(page.component);
5979
+ if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showManagedOverlay(page.component, intent, componentInstanceOrigin);
5980
+ else targetProcessed.component = estreUi.showManagedOverlay(page.component, u, componentInstanceOrigin);
5653
5981
  } else if (page.isMenu) {
5654
- if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showMenuArea(page.component, intent);
5655
- else targetProcessed.component = estreUi.showMenuArea(page.component);
5982
+ if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showMenuArea(page.component, intent, componentInstanceOrigin);
5983
+ else targetProcessed.component = estreUi.showMenuArea(page.component, u, componentInstanceOrigin);
5656
5984
  } else if (page.isBlinded) {
5657
- if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showInstantBlinded(page.component, intent);
5658
- else targetProcessed.component = estreUi.showInstantBlinded(page.component);
5985
+ if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.showInstantBlinded(page.component, intent, componentInstanceOrigin);
5986
+ else targetProcessed.component = estreUi.showInstantBlinded(page.component, u, componentInstanceOrigin);
5659
5987
  } else if (component.isModal) {
5660
- if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.openModalTab(page.component, component, intent);
5661
- else targetProcessed.component = estreUi.openModalTab(page.component, component);
5988
+ if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.openModalTab(page.component, component, intent, componentInstanceOrigin);
5989
+ else targetProcessed.component = estreUi.openModalTab(page.component, component, u, componentInstanceOrigin);
5662
5990
  } else {
5663
- if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.switchRootTab(page.component, intent);
5664
- else targetProcessed.component = estreUi.mainCurrentOnTop == component || estreUi.switchRootTab(page.component, intent);
5991
+ if (!isIntentNone && (page.isComponent || isRootMain)) targetProcessed.component = estreUi.switchRootTab(page.component, intent, componentInstanceOrigin);
5992
+ else targetProcessed.component = estreUi.mainCurrentOnTop == component || estreUi.switchRootTab(page.component, intent, u, componentInstanceOrigin);
5665
5993
  }
5666
5994
  success = targetProcessed.component;
5667
5995
  }
@@ -5682,19 +6010,23 @@ class EstreUiPageManager {
5682
6010
  if (pid.indexOf("$") < 0) pid = this.findPid(pid);
5683
6011
  const page = this.get(pid);
5684
6012
  if (page == null) return null;
6013
+ page.setInstanceOrigin(instanceOrigin);
5685
6014
  const sections = page.sections;
5686
6015
  if (sections == null) return null;
5687
6016
 
5688
- var component = sections[page.component];
6017
+ var component = sections[page.componentInstanceId];
5689
6018
  if (component == null) return null;
5690
6019
  var container = null;
5691
6020
  var article = null;
6021
+ const componentInstanceOrigin = page.componentInstanceOrigin;
6022
+ const containerInstanceOrigin = page.containerInstanceOrigin;
6023
+ const articleInstanceOrigin = page.articleInstanceOrigin;
5692
6024
  var targetProcessed = { component: null, container: null, article: null };
5693
6025
  if (page.container != null) {
5694
- container = component.containers[page.container];
6026
+ container = component.containers[page.containerInstanceId];
5695
6027
  if (container != null) {
5696
6028
  if (page.article != null) {
5697
- article = container.articles[page.article];
6029
+ article = container.articles[page.articleInstanceId];
5698
6030
  if (article != null) {
5699
6031
  targetProcessed.article = article.hide();
5700
6032
  }
@@ -5717,7 +6049,7 @@ class EstreUiPageManager {
5717
6049
  return targetProcessed[page.hostType];
5718
6050
  }
5719
6051
 
5720
- closePage(pid, closeHost = false, instanceOrigin = null) {
6052
+ closePage(pid, closeHost = false, instanceOrigin) {
5721
6053
  return postPromise(resolve => {
5722
6054
  postQueue(async _ => {
5723
6055
  if (pid.indexOf("!") > -1) pid = this.#managedPidMap[pid.replace(/^\!/, "")];
@@ -5727,37 +6059,41 @@ class EstreUiPageManager {
5727
6059
  if (pid.indexOf("$") < 0) pid = this.findPid(pid);
5728
6060
  const page = this.get(pid);
5729
6061
  if (page == null) resolve(null);
6062
+ page.setInstanceOrigin(instanceOrigin);
5730
6063
  const sections = page.sections;
5731
6064
  if (sections == null) resolve(null);
5732
6065
 
5733
- var component = sections[page.component];
6066
+ var component = sections[page.componentInstanceId];
5734
6067
  if (component == null) resolve(null);
5735
6068
  var container = null;
5736
6069
  var article = null;
6070
+ const componentInstanceOrigin = page.componentInstanceOrigin;
6071
+ const containerInstanceOrigin = page.containerInstanceOrigin;
6072
+ const articleInstanceOrigin = page.articleInstanceOrigin;
5737
6073
  var targetProcessed = { component: null, container: null, article: null };
5738
6074
  if (page.container != null) {
5739
- container = component.containers[page.container];
6075
+ container = component.containers[page.containerInstanceId];
5740
6076
  if (container != null) {
5741
6077
  if (page.article != null) {
5742
- article = container.articles[page.article];
6078
+ article = container.articles[page.articleInstanceId];
5743
6079
  if (article != null) {
5744
- targetProcessed.article = await container.closeArticle(page.article);
6080
+ targetProcessed.article = await container.closeArticle(page.article, articleInstanceOrigin);
5745
6081
  }
5746
6082
  }
5747
6083
  if (page.isContainer || closeHost || (page.isArticle && page.articleIsStatic && container.isArticlesAllyStatic)) {
5748
- targetProcessed.container = await component.closeContainer(page.container);
6084
+ targetProcessed.container = await component.closeContainer(page.container, containerInstanceOrigin);
5749
6085
  }
5750
6086
  }
5751
6087
  }
5752
6088
  if (page.isComponent || closeHost || (!page.isComponent && page.containerIsStatic && component.isContainersAllyStatic)) {
5753
6089
  if (page.isOverlay) {
5754
- targetProcessed.component = await estreUi.closeManagedOverlay(page.component);
6090
+ targetProcessed.component = await estreUi.closeManagedOverlay(page.component, componentInstanceOrigin);
5755
6091
  } else if (page.isMenu) {
5756
- targetProcessed.component = await estreUi.closeMenuArea(page.component);
6092
+ targetProcessed.component = await estreUi.closeMenuArea(page.component, componentInstanceOrigin);
5757
6093
  } else if (page.isBlinded) {
5758
- targetProcessed.component = await estreUi.closeInstantBlinded(page.component);
6094
+ targetProcessed.component = await estreUi.closeInstantBlinded(page.component, componentInstanceOrigin);
5759
6095
  } else if (component.isModal) {
5760
- targetProcessed.component = await estreUi.closeModalTab(page.component, $(component));
6096
+ targetProcessed.component = await estreUi.closeModalTab(page.component, $(component), componentInstanceOrigin);
5761
6097
  } else {
5762
6098
  targetProcessed.component = await estreUi.switchRootTab("home");
5763
6099
  }
@@ -5854,14 +6190,20 @@ class EstreHandle {
5854
6190
  get [uis.checkboxAlly]() { return EstreCheckboxAllyHandle; },
5855
6191
 
5856
6192
  get [uis.toasterSlot]() { return EstreToasterSlotHandle; },
6193
+ get [uis.multiDialSlot]() { return EstreMultiDialSlotHandle; },
5857
6194
 
5858
6195
  get [uis.customSelectorBar]() { return EstreCustomSelectorBarHandle; },
5859
6196
  get [uis.monthSelectorBar]() { return EstreMonthSelectorBarHandle; },
5860
6197
 
5861
6198
 
5862
6199
  get [uis.dateShower]() { return EstreDateShowerHandle; },
6200
+ get [uis.liveTimestamp]() { return EstreLiveTimestampHandle; },
6201
+
6202
+ get [uis.onClickSetText]() { return EstreOnClickSetTextHandle; },
6203
+ get [uis.onClickSetHtml]() { return EstreOnClickSetHtmlHandle; },
5863
6204
 
5864
6205
  get [uis.exportedContent]() { return EstreExportedContentHandle; },
6206
+ get [uis.dataHelpAlert]() { return EstreHelpAlertHandle; },
5865
6207
 
5866
6208
  get [uis.ezHidable]() { return EstreEzHidableHandle; },
5867
6209
  get [uis.fixedAccess]() { return EstreFixedAccessHandle; },
@@ -5954,7 +6296,7 @@ class EstreHandle {
5954
6296
  host.unregisterHandle(specifier, element.handle);
5955
6297
  const loaded = this.activeHandle[specifier];
5956
6298
  if (loaded != null) loaded.delete(element.handle);
5957
- element.handle.release();
6299
+ element.handle?.release();
5958
6300
  }
5959
6301
 
5960
6302
 
@@ -10030,8 +10372,12 @@ class EstreMinimalScheduler {
10030
10372
  });
10031
10373
  }
10032
10374
 
10033
- buildScheduleItem(subject, time, origin, associated) {
10375
+ buildScheduleItem(subject, time, origin, associated, itemAdditionalClass) {
10034
10376
  const item = doc.ce(li, uis.scheduleItem);
10377
+ if (itemAdditionalClass != n) kindCase(itemAdditionalClass, {
10378
+ [STRING]: _ => item.className += " " + itemAdditionalClass,
10379
+ [_ARRAY]: _ => itemAdditionalClass.forEach(cls => item.classList.add(cls)),
10380
+ });
10035
10381
  const block = doc.ce(div, uis.schedule);
10036
10382
  const subjectLine = doc.ce(div, "subject_line");
10037
10383
  subjectLine.append(doc.ce(sp, "subject", subject));
@@ -11340,9 +11686,9 @@ class EstreCheckboxAllyHandle extends EstreHandle {
11340
11686
 
11341
11687
 
11342
11688
  /**
11343
- * Toaster slots handle
11689
+ * Multi dial slot handle
11344
11690
  */
11345
- class EstreToasterSlotHandle extends EstreHandle {
11691
+ class EstreMultiDialSlotHandle extends EstreHandle {
11346
11692
 
11347
11693
  // constants
11348
11694
 
@@ -11351,15 +11697,91 @@ class EstreToasterSlotHandle extends EstreHandle {
11351
11697
 
11352
11698
 
11353
11699
  // open property
11354
-
11700
+ $dialHolder;
11701
+ dialHolder;
11702
+ $dialBounds;
11703
+ $dialHosts;
11704
+ $dialPrefixes;
11705
+ $dialSuffixes;
11706
+ $dialDividers;
11707
+
11708
+
11355
11709
  // enclosed property
11710
+ #itemTableOrigin = [];
11711
+ #itemAlignsOrigin = [];
11712
+ #itemPrefixesOrigin = [];
11713
+ #itemSuffixesOrigin = [];
11714
+ #itemDividersOrigin = [];
11715
+
11716
+ #itemSelectionObserver = [];
11717
+ #itemTableProxy = [];
11718
+
11719
+ #itemTable;
11720
+ #itemAligns;
11721
+ #itemPrefixes;
11722
+ #itemSuffixes;
11723
+ #itemDividers;
11356
11724
 
11725
+ #initialItemSelectionIndexes = [];
11726
+ #itemSelectionIndexes = [];
11727
+ #itemSelectionValues = [];
11728
+
11729
+ #itemSelectionIndexesProxy = [];
11730
+ #itemSelectionValuesProxy = [];
11731
+
11732
+ #onSelectionChanged;
11733
+
11734
+ #isInit = f;
11735
+
11357
11736
 
11358
11737
  // getter and setter
11738
+ get itemTable() { return this.#itemTable; }
11739
+ set itemTable(value) { this.updateItemTable(value); }
11740
+ get itemAligns() { return this.#itemAligns; }
11741
+ set itemAligns(value) { this.updateItemAligns(value); }
11742
+ get itemPrefixes() { return this.#itemPrefixes; }
11743
+ set itemPrefixes(value) { this.updateItemPrefixes(value); }
11744
+ get itemSuffixes() { return this.#itemSuffixes; }
11745
+ set itemSuffixes(value) { this.updateItemSuffixes(value); }
11746
+ get itemDividers() { return this.#itemDividers; }
11747
+ set itemDividers(value) { this.updateItemDividers(value); }
11748
+
11749
+ get dataset() { return new Proxy({
11750
+ table: this.#itemTable,
11751
+ aligns: this.#itemAligns,
11752
+ prefixes: this.#itemPrefixes,
11753
+ suffixes: this.#itemSuffixes,
11754
+ dividers: this.#itemDividers,
11755
+ }, {
11756
+ set: (target, property, value) => {
11757
+ equalCase(property, {
11758
+ table: _ => this.updateItemTable(value),
11759
+ aligns: _ => this.updateItemAligns(value),
11760
+ prefixes: _ => this.updateItemPrefixes(value),
11761
+ suffixes: _ => this.updateItemSuffixes(value),
11762
+ dividers: _ => this.updateItemDividers(value),
11763
+ [def]: _ => target[property] = value,
11764
+ });
11765
+ return true;
11766
+ }
11767
+ }); }
11768
+ set dataset(value) { this.setDataset(value); }
11359
11769
 
11770
+ get itemSelectionIndexes() { return this.#itemSelectionIndexesProxy; }
11771
+ set itemSelectionIndexes(value) { this.#setSelectionIndexes(value); }
11772
+ get itemSelectionValues() { return this.#itemSelectionValuesProxy; }
11773
+ set itemSelectionValues(value) { this.#setSelectionValues(value); }
11774
+ get itemSelections() {
11775
+ const selections = [];
11776
+ for (let i=0; i<this.#itemSelectionIndexes.length; i++) {
11777
+ selections.push([this.#itemSelectionIndexes[i], this.#itemSelectionValues[i]]);
11778
+ }
11779
+ return selections;
11780
+ }
11360
11781
 
11361
- constructor(toasterSlot, host) {
11362
- super(toasterSlot, host);
11782
+
11783
+ constructor(multiDialSlot, host) {
11784
+ super(multiDialSlot, host);
11363
11785
  }
11364
11786
 
11365
11787
  release(remove) {
@@ -11368,93 +11790,697 @@ class EstreToasterSlotHandle extends EstreHandle {
11368
11790
 
11369
11791
  init() {
11370
11792
  super.init();
11793
+
11794
+ this.$dialHolder = this.$bound.find(uis.dialHolder);
11795
+ this.dialHolder = this.$dialHolder[0];
11796
+ this.$dialBounds = this.$dialHolder.find(uis.dialBound);
11797
+ this.$dialHosts = this.$dialBounds.find(uis.dialHost);
11371
11798
 
11372
- this.setEvent();
11799
+ this.$dialHosts[0].solid();
11800
+ const divider = this.$dialHolder.find(li + cls + c.divider).stringified();
11801
+ this.$dialHolder.attr("data-frozen-divider", divider);
11802
+ this.$dialHolder[0].solid();
11803
+
11804
+ this.loadDataset();
11373
11805
  }
11374
11806
 
11375
- setEvent() {
11376
- const inst = this;
11807
+ loadDataset() {
11808
+ try {
11809
+ const dataItemTable = this.$bound.attr(eds.itemTable);
11810
+ if (nne(dataItemTable)) this.#itemTableOrigin = Jcodd.parse(dataItemTable);
11811
+ } catch (e) {
11812
+ if (window.isLogging) console.error(e);
11813
+ }
11377
11814
 
11378
- this.$bound.click(function (e) {
11379
- e.preventDefault();
11815
+ try {
11816
+ const dataInitial = this.$bound.attr(eds.initial);
11817
+ if (nne(dataInitial)) this.#itemSelectionIndexes = Jcodd.parse(dataInitial);
11818
+ } catch (e) {
11819
+ if (window.isLogging) console.error(e);
11820
+ }
11821
+
11822
+ try {
11823
+ const dataItemAligns = this.$bound.attr(eds.itemAligns);
11824
+ if (nne(dataItemAligns)) this.#itemAlignsOrigin = Jcodd.parse(dataItemAligns);
11825
+ } catch (e) {
11826
+ if (window.isLogging) console.error(e);
11827
+ }
11380
11828
 
11381
- switch (this.dataset.toast) {
11382
- case "option":
11383
- const options = this.dataset.options;
11384
- try {
11385
- const parsed = JSON.parse(options);
11386
- toastOption(this.dataset.toastTitle ?? "", this.dataset.toastMessage ?? "", parsed, (index, value) => this.onselected?.(index, value));
11387
- } catch (e) {
11388
- if (window.isLogging) console.error(e);
11389
- }
11390
- break;
11829
+ try {
11830
+ const dataItemPrefixes = this.$bound.attr(eds.itemPrefixes);
11831
+ if (nne(dataItemPrefixes)) this.#itemPrefixesOrigin = Jcodd.parse(dataItemPrefixes);
11832
+ } catch (e) {
11833
+ if (window.isLogging) console.error(e);
11834
+ }
11391
11835
 
11392
- // <= 케이스 추가 구현
11393
- }
11836
+ try {
11837
+ const dataItemSuffixes = this.$bound.attr(eds.itemSuffixes);
11838
+ if (nne(dataItemSuffixes)) this.#itemSuffixesOrigin = Jcodd.parse(dataItemSuffixes);
11839
+ } catch (e) {
11840
+ if (window.isLogging) console.error(e);
11841
+ }
11394
11842
 
11395
- return false;
11396
- });
11843
+ try {
11844
+ const dataItemDividers = this.$bound.attr(eds.itemDividers);
11845
+ if (nne(dataItemDividers)) this.#itemDividersOrigin = Jcodd.parse(dataItemDividers);
11846
+ } catch (e) {
11847
+ if (window.isLogging) console.error(e);
11848
+ }
11397
11849
 
11850
+ this.updateAll();
11398
11851
  }
11399
- }
11400
-
11401
-
11402
-
11403
- /**
11404
- * Estre custom selector bar handle
11405
- */
11406
- class EstreCustomSelectorBarHandle extends EstreHandle {
11407
-
11408
- // constants
11409
11852
 
11853
+ get$dialHost(boundIndex) {
11854
+ return this.$dialHosts[boundIndex]?.let(it => $(it));
11855
+ }
11410
11856
 
11411
- // statics
11857
+ getDialItems(boundIndex) {
11858
+ return this.get$dialHost(boundIndex).find(c.c + li);
11859
+ }
11412
11860
 
11861
+ setDataset(dataset = { table: [[]], initial: [], aligns: [], prefixes: [], suffixes: [], dividers: [] }) {
11862
+ this.#itemTableOrigin = dataset.table;
11863
+ this.#itemSelectionIndexes = dataset.initial;
11864
+ this.#itemAlignsOrigin = dataset.aligns;
11865
+ this.#itemPrefixesOrigin = dataset.prefixes;
11866
+ this.#itemSuffixesOrigin = dataset.suffixes;
11867
+ this.#itemDividersOrigin = dataset.dividers;
11868
+ this.updateAll();
11869
+ }
11413
11870
 
11414
- // open property
11415
- $selectorBtn;
11871
+ updateAll() {
11872
+ this.updateItemTable();
11873
+ this.updateItemAligns();
11874
+ this.updateItemPrefixes();
11875
+ this.updateItemSuffixes();
11876
+ this.updateItemDividers();
11877
+ }
11416
11878
 
11417
- $prevBtn;
11418
- $nextBtn;
11879
+ updateItemTable(itemTable = this.#itemTableOrigin, itemSelectionIndexes = this.#itemSelectionIndexes) {
11880
+ const isInit = this.#isInit;
11881
+ if (!isInit) this.#isInit = t;
11419
11882
 
11420
- $selectionsList;
11421
-
11422
- // enclosed property
11423
- #selections = [];
11424
- #currentIndex;
11883
+ itemTable ??= [];
11884
+ const isNew = itemTable != this.#itemTableOrigin;
11885
+ if (isNew) {
11886
+ this.#itemTableOrigin = itemTable;
11887
+ this.#itemTableProxy = [];
11888
+ this.#itemSelectionObserver = [];
11889
+ }
11425
11890
 
11426
- #onBuildSelector = $selectorBtn => doc.ce(sp);
11427
- #onBuildSelectionsItem = (index, id, item, button) => doc.ce(sp, n, id);
11891
+ if (itemSelectionIndexes.length != itemTable.length) {
11892
+ itemSelectionIndexes = [];
11893
+ for (let i=itemSelectionIndexes.length; i<itemTable.length; i++) itemSelectionIndexes[i] = 0;
11894
+ }
11895
+ if (itemSelectionIndexes != this.#itemSelectionIndexes) this.#itemSelectionIndexes = itemSelectionIndexes;
11896
+ this.#itemSelectionIndexesProxy = new Proxy(itemSelectionIndexes, {
11897
+ set: (target, property, value) => {
11898
+ const index = parseInt(property);
11899
+ const isIndex = !isNaN(index);
11900
+ if (isIndex) this.#scrollInstant(this.getDialItems(index)[value]);
11901
+ else target[property] = value;
11902
+ return true;
11903
+ }
11904
+ });
11428
11905
 
11429
- #onSelected = (index, id, $selectorBtn, isUpdateOnly) => $selectorBtn.find(sp).html(id);
11906
+ const itemSelectionValues = []
11907
+ this.#itemSelectionValues = itemSelectionValues;
11908
+ for (const [index, i] of itemSelectionIndexes.entries()) {
11909
+ const value = this.#itemTableOrigin[index]?.[i];
11910
+ this.#itemSelectionValues[index] = value;
11911
+ }
11912
+ this.#itemSelectionValuesProxy = new Proxy(itemSelectionValues, {
11913
+ set: (target, property, value) => {
11914
+ const index = parseInt(property);
11915
+ const isIndex = !isNaN(index);
11916
+ if (isIndex) {
11917
+ const itemIndex = this.#itemTableOrigin[index]?.indexOf(value);
11918
+ if (itemIndex > -1) this.#scrollInstant(this.getDialItems(index)[itemIndex]);
11919
+ } else target[property] = value;
11920
+ return true;
11921
+ }
11922
+ });
11430
11923
 
11924
+ this.$dialHolder.empty();
11925
+ this.dialHolder.worm({ offset: 0 }, c.frozenDivider);
11926
+ for (var [index, list] of itemTable.entries()) {
11927
+ this.dialHolder.worm({ boundIndex: index });
11928
+ this.dialHolder.worm({ offset: index + 1 }, c.frozenDivider);
11929
+ }
11930
+ const updateBoundLinks = _ => {
11931
+ this.$dialBounds = this.$dialHolder.find(uis.dialBound);
11932
+ this.$dialHosts = this.$dialBounds.find(c.c + uis.dialHost);
11933
+ this.$dialPrefixes = this.$dialHolder.find(c.c + li + c.c + uis.prefix + c.c + sp);
11934
+ this.$dialSuffixes = this.$dialHolder.find(c.c + li + c.c + uis.suffix + c.c + sp);
11935
+ this.$dialDividers = this.$dialHolder.find(c.c + uis.divider + c.c + sp);
11936
+ }
11937
+ updateBoundLinks();
11938
+
11939
+ for (var [index, list] of itemTable.entries()) {
11940
+ this.#setItemBoundEvents(index);
11941
+ this.updateItemBound(index, list);
11942
+ }
11943
+
11944
+ if (!isInit) this.#isInit = f;
11945
+
11946
+ return this.#itemTable = new Proxy(this.#itemTableProxy, {
11947
+ set: (target, property, value) => {
11948
+ const index = parseInt(property);
11949
+ const isIndex = !isNaN(index);
11950
+ target[property] = isIndex ? this.#setItemTableProxy(index, value) : value;
11951
+ if (isIndex) {
11952
+ const boundLength = this.$dialBounds.length;
11953
+ if (boundLength > index) this.updateItemBound(index, value);
11954
+ else {
11955
+ for (let i=boundLength; i<=index; i++) {
11956
+ this.dialHolder.worm({ boundIndex: i });
11957
+ this.dialHolder.worm({ offset: i + 1 }, c.frozenDivider);
11958
+ }
11959
+ updateBoundLinks();
11431
11960
 
11432
- // getter and setter
11433
- get prev() { return this.#currentIndex - 1; }
11434
- get current() { return this.#currentIndex; }
11435
- get next() { return this.#currentIndex + 1; }
11436
-
11437
- get prevId() { return this.#currentIndex > 0 ? this.#selections[this.prev] : n; }
11438
- get currentId() { return this.#selections[this.current]; }
11439
- get nextId() { return this.#currentIndex < this.#selections.length - 1 ? this.#selections[this.next] : n; }
11961
+ for (let i=boundLength; i<=index; i++) {
11962
+ this.#setItemBoundEvents(i);
11963
+ this.updateItemBound(i, i == index ? value : []);
11964
+ }
11965
+ }
11966
+ }
11967
+ return true;
11968
+ },
11969
+ deleteProperty: (target, property) => {
11970
+ delete target[property];
11971
+ const index = parseInt(property);
11972
+ const isIndex = !isNaN(index);
11973
+ if (isIndex) {
11974
+ this.$dialBounds[index].remove();
11975
+ this.$dialHolder.find(c.c + uis.dialDivider)[index + 1].remove();
11976
+ const dividerLength = this.#itemDividers.length;
11977
+ const dividerCount = this.$dialDividers.length;
11978
+ updateBoundLinks();
11979
+ this.#itemTableProxy.splice(index, 1);
11980
+ this.#itemAlignsOrigin.splice(index, 1);
11981
+ this.#itemPrefixesOrigin.splice(index, 1);
11982
+ this.#itemSuffixesOrigin.splice(index, 1);
11983
+ this.#itemSelectionObserver.splice(index, 1);
11984
+ if (dividerLength == 3 && dividerCount != 3) this.updateItemDividers();
11985
+ else this.#itemDividersOrigin.splice(index + 1, 1);
11986
+ }
11987
+ return true;
11988
+ }
11989
+ });
11990
+ }
11440
11991
 
11441
- get isUsePopupSelector() { return this.$bound.attr(eds.usePopupSelector) == t1; }
11992
+ #setItemBoundEvents(index, itemBound = this.$dialBounds[index]) {
11993
+ const inst = this;
11994
+ const $itemBound = $(itemBound);
11442
11995
 
11996
+ $itemBound.on(c.wheel, function (e) {
11997
+ e.preventDefault();
11443
11998
 
11444
- constructor(checkboxAlly, host) {
11445
- super(checkboxAlly, host);
11446
- }
11999
+ const delta = Math.sign(e.originalEvent.deltaY);
12000
+ const selected = parseInt(this.dataset.selected);
12001
+ const $item = $(this).find(c.c + ul + c.c + li + aiv(eds.index, Math.min(Math.max(0, selected + delta), inst.#itemTable[index].length - 1) ) );
12002
+ $item.click();
11447
12003
 
11448
- release(remove) {
11449
- super.release(remove);
11450
- }
12004
+ return false;
12005
+ });
11451
12006
 
11452
- init() {
11453
- super.init();
11454
12007
 
11455
- this.$selectorBtn = this.$bound.find(c.c + cls + "bar_side" + c.c + btn + cls + "selector");
12008
+ const threshold = 1;
12009
+ const rootMargin = "0px";
11456
12010
 
11457
- this.$prevBtn = this.$bound.find(c.c + cls + "bar_side" + c.c + btn + cls + "prev");
12011
+ this.#itemSelectionObserver[index] = new IntersectionObserver(entries => {
12012
+ for (const entry of entries) {
12013
+ if (entry.isIntersecting) {
12014
+ const idx = entry.target.dataset.index;
12015
+ const i = parseInt(idx);
12016
+ itemBound.dataset.selected = idx;
12017
+ this.#onSelected(index, i);
12018
+ }
12019
+ }
12020
+ }, {
12021
+ root: itemBound,
12022
+ rootMargin,
12023
+ threshold
12024
+ });
12025
+
12026
+ const ro = new ResizeObserver((entries) => {
12027
+ for (const entry of entries) {
12028
+ const items = this.getDialItems(index);
12029
+ const itemHeight = items[0]?.offsetHeight ?? 0;
12030
+ const halfHeight = parseInt(itemHeight / 2);
12031
+ const padding = getComputedStyle(entry.target.querySelector(ul)).padding;
12032
+ const paddings = padding.split(s).map(it => parseInt(it));
12033
+ for (let i=0; i<paddings.length; i+=2) paddings[i] = Math.max(paddings[i] - halfHeight, 0);
12034
+ const rootMargin = paddings.map(it => hp + it + c.px).join(s);
12035
+
12036
+ const current = this.#itemSelectionObserver[index];
12037
+
12038
+ if (current != null) for (const elem of items) current.unobserve(elem);
12039
+
12040
+ this.#itemSelectionObserver[index] = new IntersectionObserver(entries => {
12041
+ for (const entry of entries) {
12042
+ if (entry.isIntersecting) {
12043
+ const idx = entry.target.dataset.index;
12044
+ const i = parseInt(idx);
12045
+ itemBound.dataset.selected = idx;
12046
+ this.#onSelected(index, i);
12047
+ }
12048
+ }
12049
+ }, {
12050
+ root: itemBound,
12051
+ rootMargin,
12052
+ threshold
12053
+ });
12054
+
12055
+ for (const item of items) this.#setItemEvent(index, item.dataset.index, item);
12056
+ }
12057
+ });
12058
+
12059
+ ro.observe(itemBound);
12060
+
12061
+ return ro;
12062
+ }
12063
+
12064
+ updateItemBound(index, list) {
12065
+ const host = this.$dialHosts[index];
12066
+ if (host != n) {
12067
+ const isInit = this.#isInit;
12068
+ if (!isInit) this.#isInit = t;
12069
+
12070
+ const $host = $(host);
12071
+ const align = typeCase(list?.[0]?.let(it => parseFloat(it).let(num => isNaN(num) ? it : num)), {
12072
+ [NUMBER]: "right",
12073
+ [STRING]: "left",
12074
+ [DEFAULT]: c.center,
12075
+ });
12076
+ $host.attr(eds.align, align);
12077
+ if (list.length < 1) host.melt({ index: "0", value: "-" });
12078
+ else {
12079
+ $host.empty();
12080
+ for (const [index, value] of list.entries()) {
12081
+ host.worm({ index, value, dataPlaceholder: "" });
12082
+ }
12083
+ const $items = $host.find(c.c + li);
12084
+ for (let idx = 0; idx < $items.length; idx++) {
12085
+ this.#setItemEvent(index, idx, $items[idx]);
12086
+ }
12087
+ }
12088
+
12089
+ const $items = $host.find(c.c + li);
12090
+ const selectedIndex = Math.min(Math.max(0, this.#itemSelectionIndexes[index] ?? 0), $items.length - 1);
12091
+ this.#scrollInstant($items[selectedIndex]);
12092
+
12093
+ if (!isInit) this.#isInit = f;
12094
+
12095
+ return this.#setItemTableProxy(index, list);
12096
+ } else return this.#itemTable[index];
12097
+ }
12098
+
12099
+ #setItemTableProxy(boundIndex, list) {
12100
+ return this.#itemTableProxy[boundIndex] = new Proxy(list ?? [], {
12101
+ set: (target, property, value) => {
12102
+ const index = parseInt(property);
12103
+ const isIndex = !isNaN(index);
12104
+ target[property] = value;
12105
+ if (isIndex) {
12106
+ const host = this.$dialHosts[boundIndex];
12107
+ const $host = $(host);
12108
+ const $items = $host.find(c.c + li);
12109
+ const length = $items.length;
12110
+ if (length > index) {
12111
+ const $item = $($items[index]);
12112
+ const $span = $item.find(c.c + sp);
12113
+ $span.html(value);
12114
+ } else for (let i=length; i<=index; i++) {
12115
+ host.worm({ index: i, value: i == index ? value : "" });
12116
+ this.#setItemEvent(boundIndex, i);
12117
+ }
12118
+ }
12119
+ return true;
12120
+ },
12121
+ deleteProperty: (target, property) => {
12122
+ delete target[property];
12123
+ const index = parseInt(property);
12124
+ const isIndex = !isNaN(index);
12125
+ if (isIndex) this.getDialItems(boundIndex)[index].remove();
12126
+ return true;
12127
+ }
12128
+ });
12129
+ }
12130
+
12131
+ #setItemEvent(boundIndex, index, item = this.getDialItems(boundIndex)[index], observer = this.#itemSelectionObserver[boundIndex]) {
12132
+ const inst = this;
12133
+ observer.observe(item);
12134
+ $(item).off(c.click).click(function (e) {
12135
+ e.preventDefault();
12136
+
12137
+ inst.#scrollSmooth(this);
12138
+
12139
+ return false;
12140
+ });
12141
+ }
12142
+
12143
+ updateItemAligns(itemAligns = this.#itemAlignsOrigin) {
12144
+ itemAligns ??= [];
12145
+ if (itemAligns != this.#itemAlignsOrigin) this.#itemAlignsOrigin = itemAligns;
12146
+ for (const [index, value] of itemAligns.entries()) {
12147
+ const align = typeUndefined(value) ? "" : value == n ? c.center : value ? c.right : c.left;
12148
+ this.get$dialHost(index).attr(eds.align, align);
12149
+ }
12150
+ this.#itemAligns = new Proxy(itemAligns, {
12151
+ set: (target, property, value) => {
12152
+ const index = parseInt(property);
12153
+ const isIndex = !isNaN(index);
12154
+ target[property] = value;
12155
+ if (isIndex && index < this.$dialHosts.length) {
12156
+ const align = typeUndefined(value) ? "" : value == n ? c.center : value ? c.right : c.left;
12157
+ this.get$dialHost(index).attr(eds.align, align);
12158
+ }
12159
+ return true;
12160
+ },
12161
+ deleteProperty: (target, property) => {
12162
+ delete target[property];
12163
+ return true;
12164
+ }
12165
+ });
12166
+ }
12167
+
12168
+ updateItemPrefixes(itemPrefixes = this.#itemPrefixesOrigin) {
12169
+ itemPrefixes ??= [];
12170
+ if (itemPrefixes != this.#itemPrefixesOrigin) this.#itemPrefixesOrigin = itemPrefixes;
12171
+ for (const [index, value] of itemPrefixes.entries()) {
12172
+ $(this.$dialPrefixes[index]).html(value);
12173
+ }
12174
+ this.#itemPrefixes = new Proxy(itemPrefixes, {
12175
+ set: (target, property, value) => {
12176
+ const index = parseInt(property);
12177
+ const isIndex = !isNaN(index);
12178
+ target[property] = value;
12179
+ if (isIndex && index < this.$dialPrefixes.length) {
12180
+ $(this.$dialPrefixes[index]).html(value);
12181
+ }
12182
+ return true;
12183
+ },
12184
+ deleteProperty: (target, property) => {
12185
+ delete target[property];
12186
+ return true;
12187
+ }
12188
+ });
12189
+ }
12190
+
12191
+ updateItemSuffixes(itemSuffixes = this.#itemSuffixesOrigin) {
12192
+ itemSuffixes ??= [];
12193
+ if (itemSuffixes != this.#itemSuffixesOrigin) this.#itemSuffixesOrigin = itemSuffixes;
12194
+ for (const [index, value] of itemSuffixes.entries()) {
12195
+ $(this.$dialSuffixes[index]).html(value);
12196
+ }
12197
+ this.#itemSuffixes = new Proxy(itemSuffixes, {
12198
+ set: (target, property, value) => {
12199
+ const index = parseInt(property);
12200
+ const isIndex = !isNaN(index);
12201
+ target[property] = value;
12202
+ if (isIndex && index < this.$dialSuffixes.length) {
12203
+ $(this.$dialSuffixes[index]).html(value);
12204
+ }
12205
+ return true;
12206
+ },
12207
+ deleteProperty: (target, property) => {
12208
+ delete target[property];
12209
+ return true;
12210
+ }
12211
+ });
12212
+ }
12213
+
12214
+ updateItemDividers(itemDividers = this.#itemDividersOrigin) {
12215
+ itemDividers ??= [];
12216
+ if (itemDividers != this.#itemDividersOrigin) this.#itemDividersOrigin = itemDividers;
12217
+ if (itemDividers.length == 3) {
12218
+ const lastIndex = this.$dialDividers.length - 1;
12219
+ for (let i=0; i<this.$dialDividers.length; i++) {
12220
+ if (i == 0) $(this.$dialDividers[i]).html(itemDividers[0]);
12221
+ else if (i == lastIndex) $(this.$dialDividers[i]).html(itemDividers[2]);
12222
+ else $(this.$dialDividers[i]).html(itemDividers[1]);
12223
+ }
12224
+ } else for (const [index, value] of itemDividers.entire) {
12225
+ $(this.$dialDividers[index]).html(value);
12226
+ }
12227
+ this.#itemDividers = new Proxy(itemDividers, {
12228
+ set: (target, property, value) => {
12229
+ const index = parseInt(property);
12230
+ const isIndex = !isNaN(index);
12231
+ target[property] = value;
12232
+ if (isIndex) {
12233
+ if (target.length == 3 && index > 0) {
12234
+ const lastIndex = this.$dialDividers.length - 1;
12235
+ if (index == 3) $(this.$dialDividers[lastIndex]).html(value);
12236
+ else if (index == 2) for (let i=1; i<lastIndex; i++) $(this.$dialDividers[i]).html(value);
12237
+ } else if (index < this.$dialDividers.length) {
12238
+ $(this.$dialDividers[index]).html(value);
12239
+ }
12240
+ }
12241
+ return true;
12242
+ },
12243
+ deleteProperty: (target, property) => {
12244
+ delete target[property];
12245
+ return true;
12246
+ }
12247
+ });
12248
+ }
12249
+
12250
+
12251
+ setOnSelected(callback = (boundIndex, index, value, selectionIndexes, selectionValues) => {}) {
12252
+ this.#onSelectionChanged = callback;
12253
+ }
12254
+
12255
+ #onSelected(boundIndex, index, value = this.#itemTable[boundIndex][index]) {
12256
+ if (this.#initialItemSelectionIndexes[boundIndex] == n) {
12257
+ const idx = this.#itemSelectionIndexes[boundIndex];
12258
+ if (idx != n) {
12259
+ const item = this.getDialItems(boundIndex)?.[idx];
12260
+ if (item != n && this.$dialBounds[boundIndex].dataset.selected != idx) {
12261
+ const isInit = this.#isInit;
12262
+ if (!isInit) this.#isInit = t;
12263
+ this.#scrollInstant(item);
12264
+ if (!isInit) this.#isInit = f;
12265
+ return;
12266
+ }
12267
+ }
12268
+ this.#initialItemSelectionIndexes[boundIndex] = index;
12269
+ }
12270
+ if (!this.isInit) {
12271
+ if (window.isVerbosely) console.log("Item selected: [" + idx + "] " + value);
12272
+ this.#itemSelectionIndexes[boundIndex] = index;
12273
+ this.#itemSelectionValues[boundIndex] = value;
12274
+
12275
+ const selectionIndexes = this.#itemSelectionIndexes.mock;
12276
+ const selectionValues = this.#itemSelectionValues.mock;
12277
+ this.#onSelectionChanged?.(boundIndex, index, value, selectionIndexes, selectionValues);
12278
+ }
12279
+ }
12280
+
12281
+ #setSelectionIndexes(selectionIndexes = [], setByEvent = t) {
12282
+ const isInit = this.#isInit;
12283
+ const isInitializing = !setByEvent;
12284
+ const isSingleEvent = setByEvent == n;
12285
+ if (isInitializing && !isInit) this.#isInit = t;
12286
+ for (let i=0; i<this.#itemTableOrigin.length; i++) {
12287
+ const index = selectionIndexes[i];
12288
+ if (index != n) {
12289
+ if (isInitializing) {
12290
+ this.#itemSelectionIndexes[i] = index;
12291
+ this.#itemSelectionValues[i] = this.#itemTableOrigin[i]?.[index];
12292
+ }
12293
+ if (this.$dialBounds[i].dataset.selected != index) {
12294
+ const items = this.getDialItems(i);
12295
+ this.#scrollInstant(items[index]);
12296
+ }
12297
+ }
12298
+ }
12299
+ if (isInitializing && !isInit) this.#isInit = f;
12300
+ if (isSingleEvent) this.#onSelectionChanged?.(n, n, n, this.#itemSelectionIndexes.mock, this.itemSelectionValues.mock);
12301
+ return this.itemSelectionIndexes;
12302
+ }
12303
+
12304
+ #setSelectionValues(selectionValues = [], setByEvent = t) {
12305
+ const isInit = this.#isInit;
12306
+ const isInitializing = !setByEvent;
12307
+ const isSingleEvent = setByEvent == n;
12308
+ if (isInitializing && !isInit) this.#isInit = t;
12309
+ for (let i=0; i<this.#itemTableOrigin.length; i++) {
12310
+ const value = selectionValues[i];
12311
+ if (value != n) {
12312
+ const index = this.#itemTableOrigin[i]?.indexOf(value);
12313
+ if (index != n) {
12314
+ if (isInitializing) {
12315
+ this.#itemSelectionIndexes[i] = index;
12316
+ this.#itemSelectionValues[i] = value;
12317
+ }
12318
+ if (index > -1 && this.$dialBounds[i].dataset.selected != index) {
12319
+ const items = this.getDialItems(i);
12320
+ this.#scrollInstant(items[index]);
12321
+ }
12322
+ }
12323
+ }
12324
+ }
12325
+ if (isInitializing && !isInit) this.#isInit = f;
12326
+ if (isSingleEvent) this.#onSelectionChanged?.(n, n, n, this.#itemSelectionIndexes.mock, this.itemSelectionValues.mock);
12327
+ return this.itemSelectionValues;
12328
+ }
12329
+
12330
+ setSelectionsByIndexes(selectionIndexes = [], isUpdateOnly = n) {
12331
+ return this.#setSelectionIndexes(selectionIndexes, isUpdateOnly?.let(it => !it));
12332
+ }
12333
+
12334
+ setSelectionsByValues(selectionValues = [], isUpdateOnly = n) {
12335
+ return this.#setSelectionValues(selectionValues, isUpdateOnly?.let(it => !it));
12336
+ }
12337
+
12338
+ #scrollInstant(elem, host = elem?.parentElement) {
12339
+ // elem?.scrollIntoView({ behavior: c.instant, block: c.center });
12340
+ if (elem != n && host != n) {
12341
+ host.scrollTop = host.scrollTop;
12342
+
12343
+ postQueue(_ => {
12344
+ const hostRect = host.getBoundingClientRect();
12345
+ const elemRect = elem.getBoundingClientRect();
12346
+
12347
+ const offset = elemRect.top - hostRect.top - (hostRect.height / 2) + (elemRect.height / 2);
12348
+ host.scrollTop += offset;
12349
+ });
12350
+ }
12351
+ }
12352
+
12353
+ #scrollSmooth(elem, host = elem?.parentElement) {
12354
+ // elem?.scrollIntoView({ behavior: c.smooth, block: c.center });
12355
+ if (elem != n && host != n) {
12356
+ const hostRect = host.getBoundingClientRect();
12357
+ const elemRect = elem.getBoundingClientRect();
12358
+
12359
+ host.scrollBy({
12360
+ top: elemRect.top - hostRect.top - (hostRect.height / 2) + (elemRect.height / 2),
12361
+ behavior: c.smooth
12362
+ });
12363
+ }
12364
+ }
12365
+ }
12366
+
12367
+
12368
+ /**
12369
+ * Toaster slot handle
12370
+ */
12371
+ class EstreToasterSlotHandle extends EstreHandle {
12372
+
12373
+ // constants
12374
+
12375
+
12376
+ // statics
12377
+
12378
+
12379
+ // open property
12380
+
12381
+ // enclosed property
12382
+
12383
+
12384
+ // getter and setter
12385
+
12386
+
12387
+ constructor(toasterSlot, host) {
12388
+ super(toasterSlot, host);
12389
+ }
12390
+
12391
+ release(remove) {
12392
+ super.release(remove);
12393
+ }
12394
+
12395
+ init() {
12396
+ super.init();
12397
+
12398
+ this.setEvent();
12399
+ }
12400
+
12401
+ setEvent() {
12402
+ const inst = this;
12403
+
12404
+ this.$bound.click(function (e) {
12405
+ e.preventDefault();
12406
+
12407
+ switch (this.dataset.toast) {
12408
+ case "option":
12409
+ const options = this.dataset.options;
12410
+ try {
12411
+ const parsed = JSON.parse(options);
12412
+ toastOption(this.dataset.toastTitle ?? "", this.dataset.toastMessage ?? "", parsed, (index, value) => this.onselected?.(index, value));
12413
+ } catch (e) {
12414
+ if (window.isLogging) console.error(e);
12415
+ }
12416
+ break;
12417
+
12418
+ // <= 케이스 추가 구현
12419
+ }
12420
+
12421
+ return false;
12422
+ });
12423
+
12424
+ }
12425
+ }
12426
+
12427
+
12428
+
12429
+ /**
12430
+ * Estre custom selector bar handle
12431
+ */
12432
+ class EstreCustomSelectorBarHandle extends EstreHandle {
12433
+
12434
+ // constants
12435
+
12436
+
12437
+ // statics
12438
+
12439
+
12440
+ // open property
12441
+ $selectorBtn;
12442
+
12443
+ $prevBtn;
12444
+ $nextBtn;
12445
+
12446
+ $selectionsList;
12447
+
12448
+ // enclosed property
12449
+ #selections = [];
12450
+ #currentIndex;
12451
+
12452
+ #onBuildSelector = $selectorBtn => doc.ce(sp);
12453
+ #onBuildSelectionsItem = (index, id, item, button) => doc.ce(sp, n, id);
12454
+
12455
+ #onSelected = (index, id, $selectorBtn, isUpdateOnly) => $selectorBtn.find(sp).html(id);
12456
+
12457
+
12458
+ // getter and setter
12459
+ get prev() { return this.#currentIndex - 1; }
12460
+ get current() { return this.#currentIndex; }
12461
+ get next() { return this.#currentIndex + 1; }
12462
+
12463
+ get prevId() { return this.#currentIndex > 0 ? this.#selections[this.prev] : n; }
12464
+ get currentId() { return this.#selections[this.current]; }
12465
+ get nextId() { return this.#currentIndex < this.#selections.length - 1 ? this.#selections[this.next] : n; }
12466
+
12467
+ get isUsePopupSelector() { return this.$bound.attr(eds.usePopupSelector) == t1; }
12468
+
12469
+
12470
+ constructor(checkboxAlly, host) {
12471
+ super(checkboxAlly, host);
12472
+ }
12473
+
12474
+ release(remove) {
12475
+ super.release(remove);
12476
+ }
12477
+
12478
+ init() {
12479
+ super.init();
12480
+
12481
+ this.$selectorBtn = this.$bound.find(c.c + cls + "bar_side" + c.c + btn + cls + "selector");
12482
+
12483
+ this.$prevBtn = this.$bound.find(c.c + cls + "bar_side" + c.c + btn + cls + "prev");
11458
12484
  this.$nextBtn = this.$bound.find(c.c + cls + "bar_side" + c.c + btn + cls + "next");
11459
12485
 
11460
12486
  this.$selectionsList = this.$bound.find(c.c + cls + "float_selections" + c.c + ul + cls + "selections");
@@ -11914,6 +12940,194 @@ class EstreDateShowerHandle extends EstreHandle {
11914
12940
  }
11915
12941
  }
11916
12942
 
12943
+ class EstreLiveTimestampHandle extends EstreHandle {
12944
+
12945
+ // constants
12946
+
12947
+
12948
+ // statics
12949
+
12950
+
12951
+ // open property
12952
+
12953
+
12954
+ // enclosed property
12955
+ #date;
12956
+
12957
+ #timeout;
12958
+
12959
+
12960
+ #nextTimeout = 1000;
12961
+
12962
+
12963
+ // getter and setter
12964
+ get date() { return new Date(this.#date); }
12965
+
12966
+ get from() { return this.$bound.attr(eds.liveTimestamp).int; }
12967
+
12968
+ get isShortSuffix() { return this.$bound.attr(eds.shortSuffix) == t1; }
12969
+
12970
+
12971
+ constructor(liveTimestamp, host) {
12972
+ super(liveTimestamp, host);
12973
+ }
12974
+
12975
+ release() {
12976
+ clearTimeout(this.#timeout);
12977
+ this.#timeout = n;
12978
+
12979
+ super.release();
12980
+ }
12981
+
12982
+ init() {
12983
+ super.init();
12984
+
12985
+ this.#date = new Date(this.from).time;
12986
+
12987
+ if (!isNaN(this.#date)) {
12988
+ this.updateDisplay();
12989
+
12990
+ this.setLive();
12991
+ }
12992
+
12993
+ return this;
12994
+ }
12995
+
12996
+ setLive() {
12997
+ if (this.#timeout != n) {
12998
+ clearTimeout(this.#timeout);
12999
+ this.#timeout = n;
13000
+ }
13001
+
13002
+ const postTimeout = _ => this.#timeout = setTimeout(_ => {
13003
+ if (!this.bound.isConnected) {
13004
+ clearTimeout(this.#timeout);
13005
+ this.#timeout = n
13006
+ return;
13007
+ }
13008
+ this.updateDisplay();
13009
+ if (this.#nextTimeout != n) postTimeout();
13010
+ else this.#timeout = n;
13011
+ }, this.#nextTimeout);
13012
+
13013
+ if (this.#nextTimeout != n) postTimeout();
13014
+ else this.#timeout = n;
13015
+ }
13016
+
13017
+ updateDisplay() {
13018
+ const suffixType = this.isShortSuffix ? "ShortSuffix" : "Suffix";
13019
+ const now = dt.t;
13020
+ const time = this.#date;
13021
+ const diff = now - time;
13022
+ let text = "";
13023
+ let nextTimeout = n;
13024
+ if (diff < 10000) {
13025
+ text = EsLocale.get("now");
13026
+ nextTimeout = 10000 - diff;
13027
+ } else {
13028
+ const texts = [];
13029
+ const ago = EsLocale.get("ago");
13030
+ if (diff < 20000) {
13031
+ texts.push(EsLocale.get("just"));
13032
+ nextTimeout = 20000 - diff;
13033
+ } else if (diff < 60000) {
13034
+ texts.push(Math.floor(diff / 1000) + EsLocale.get("seconds" + suffixType));
13035
+ nextTimeout = 10000;
13036
+ } else if (diff < 3600000) {
13037
+ texts.push(Math.floor(diff / 60000) + EsLocale.get("minutes" + suffixType));
13038
+ nextTimeout = 60000;
13039
+ } else if (diff < 86400000) {
13040
+ texts.push(Math.floor(diff / 3600000) + EsLocale.get("hours" + suffixType));
13041
+ nextTimeout = 3600000;
13042
+ } else if (diff < 604800000) {
13043
+ texts.push(Math.floor(diff / 86400000) + EsLocale.get("days" + suffixType));
13044
+ nextTimeout = 86400000;
13045
+ } else if (diff < 2592000000) texts.push(Math.floor(diff / 604800000) + EsLocale.get("weeks" + suffixType));
13046
+ else if (diff < 31104000000) texts.push(Math.floor(diff / 2592000000) + EsLocale.get("months" + suffixType));
13047
+ else texts.push(Math.floor(diff / 31104000000) + EsLocale.get("years" + suffixType));
13048
+ texts.push(ago);
13049
+ text = texts.join(s);
13050
+ }
13051
+ this.#nextTimeout = nextTimeout;
13052
+ this.$bound.html(text);
13053
+ }
13054
+ }
13055
+
13056
+
13057
+
13058
+ // on click set text
13059
+ class EstreOnClickSetTextHandle extends EstreHandle {
13060
+ // constants
13061
+
13062
+ // statics
13063
+
13064
+ // open property
13065
+
13066
+ // enclosed property
13067
+
13068
+ // getter and setter
13069
+
13070
+
13071
+ constructor(bound, host) {
13072
+ super(bound, host);
13073
+ }
13074
+
13075
+ release() {
13076
+ super.release();
13077
+ }
13078
+
13079
+ init() {
13080
+ super.init();
13081
+
13082
+ this.$bound.click(function (e) {
13083
+ e.preventDefault();
13084
+
13085
+ const text = this.dataset.onClickSetText;
13086
+ $(this).text(text);
13087
+
13088
+ return false;
13089
+ });
13090
+ }
13091
+
13092
+ }
13093
+
13094
+ // on click set html
13095
+ class EstreOnClickSetHtmlHandle extends EstreHandle {
13096
+ // constants
13097
+
13098
+ // statics
13099
+
13100
+ // open property
13101
+
13102
+ // enclosed property
13103
+
13104
+ // getter and setter
13105
+
13106
+
13107
+ constructor(bound, host) {
13108
+ super(bound, host);
13109
+ }
13110
+
13111
+ release() {
13112
+ super.release();
13113
+ }
13114
+
13115
+ init() {
13116
+ super.init();
13117
+
13118
+ this.$bound.click(function (e) {
13119
+ e.preventDefault();
13120
+
13121
+ const text = this.dataset.onClickSetHtml;
13122
+ $(this).html(text);
13123
+
13124
+ return false;
13125
+ });
13126
+ }
13127
+
13128
+ }
13129
+
13130
+
11917
13131
 
11918
13132
  // exported content
11919
13133
  class EstreExportedContentHandle extends EstreHandle {
@@ -11964,6 +13178,44 @@ class EstreExportedContentHandle extends EstreHandle {
11964
13178
  }
11965
13179
  }
11966
13180
 
13181
+ class EstreHelpAlertHandle extends EstreHandle {
13182
+
13183
+ // constants
13184
+
13185
+ // statics
13186
+
13187
+
13188
+ // open property
13189
+
13190
+
13191
+ // enclosed property
13192
+
13193
+
13194
+ // getter and setter
13195
+
13196
+
13197
+ constructor(bound, host) {
13198
+ super(bound, host);
13199
+ }
13200
+
13201
+ release() {
13202
+ super.release();
13203
+ }
13204
+
13205
+ init() {
13206
+ super.init();
13207
+
13208
+ this.$bound.click(function (e) {
13209
+ e.preventDefault();
13210
+
13211
+ alert(this.dataset.helpAlertTitle?.replace(/\\n/g, "<br />") ?? "", this.dataset.helpAlert.replace(/\\n/g, "<br />") ?? "");
13212
+
13213
+ return false;
13214
+ });
13215
+ }
13216
+ }
13217
+
13218
+
11967
13219
 
11968
13220
  // quick transitions
11969
13221
  class EstreEzHidableHandle extends EstreHandle {
@@ -13518,8 +14770,41 @@ const estreUi = {
13518
14770
  initialHistoryOffset: null,
13519
14771
  isBackwardFlow: false,
13520
14772
 
13521
- prevRootTabId: null,
13522
- prevBlindedId: null,
14773
+
14774
+ prevRootTabIds: new Set(),
14775
+ get latestRootTabId() { return [...this.prevRootTabIds].pop(); },
14776
+ get prevRootTabId() {
14777
+ const rootTabIds = this.mainSections.ways;
14778
+ let latestRootTabId = null;
14779
+ while (latestRootTabId = this.latestRootTabId) {
14780
+ this.prevRootTabIds.delete(latestRootTabId);
14781
+ if (rootTabIds.includes(latestRootTabId)) return latestRootTabId;
14782
+ }
14783
+ return null;
14784
+ },
14785
+ set prevRootTabId(id) {
14786
+ if (id == null) return;
14787
+ if (this.prevRootTabIds.has(id)) this.prevRootTabIds.delete(id);
14788
+ this.prevRootTabIds.add(id);
14789
+ },
14790
+
14791
+ prevBlindedIds: new Set(),
14792
+ get latestBlindedId() { return [...this.prevBlindedIds].pop(); },
14793
+ get prevBlindedId() {
14794
+ const blindedIds = this.blindSections.ways;
14795
+ let latestBlindedId = null;
14796
+ while (latestBlindedId = this.latestBlindedId) {
14797
+ this.prevBlindedIds.delete(latestBlindedId);
14798
+ if (blindedIds.includes(latestBlindedId)) return latestBlindedId;
14799
+ }
14800
+ return null;
14801
+ },
14802
+ set prevBlindedId(id) {
14803
+ if (id == null) return;
14804
+ if (this.prevBlindedIds.has(id)) this.prevBlindedIds.delete(id);
14805
+ this.prevBlindedIds.add(id);
14806
+ },
14807
+
13523
14808
 
13524
14809
  //getter and setter
13525
14810
  get isOpenMainMenu() { return this.$mainMenu.attr(eds.opened) == t1; },
@@ -14105,7 +15390,7 @@ const estreUi = {
14105
15390
 
14106
15391
  const currentTopHandle = this.mainCurrentOnTop;
14107
15392
  const currentTopHandleId = currentTopHandle?.id;
14108
- if (id != currentTopHandleId && currentTopHandleId != this.prevRootTabId) {
15393
+ if (id != currentTopHandleId && currentTopHandleId != this.latestRootTabId) {
14109
15394
  this.prevRootTabId = currentTopHandleId;
14110
15395
 
14111
15396
  // if (estreUi.euiState == "onReady" && currentTopHandle != null) {
@@ -14144,29 +15429,34 @@ const estreUi = {
14144
15429
  },
14145
15430
 
14146
15431
  switchRootTabPrev() {
14147
- if (this.prevRootTabId != null) {
14148
- const processed = this.switchRootTab(this.prevRootTabId);
14149
- if (processed) this.prevRootTabId = null;
15432
+ const prev = this.prevRootTabId;
15433
+ if (prev != null) {
15434
+ const processed = this.switchRootTab(prev);
14150
15435
  return processed;
14151
15436
  } else return false;
14152
15437
  },
14153
15438
 
14154
- openInstantBlinded(id, intent) {
15439
+ openInstantBlinded(id, intent, instanceOrigin) {
14155
15440
  const page = pageManager.getComponent(id);
14156
15441
  if (page == null) return null;
14157
15442
  if (page.statement == "static") return null;
14158
15443
  this.$blindArea.append(page.live);
14159
15444
  const $section = this.$blindSections.filter(eid + id);
14160
15445
  if ($section == null || $section.length < 1) return null;
14161
- const component = this.initInstantContent($section[0], intent);
15446
+ const component = this.initInstantContent($section[$section.length - 1], intent, instanceOrigin);
14162
15447
  if (component.isOnTop) component.show(false);
14163
15448
  return component;
14164
15449
  },
14165
15450
 
14166
- showInstantBlinded(id, intent) {
14167
- const $targetSection = this.$blindSections.filter(eid + id);
15451
+ showInstantBlinded(id, intent, instanceOrigin) {
15452
+ let $targetSection = this.$blindSections.filter(eid + id + (instanceOrigin?.let(it => aiv(eds.instanceOrigin, it)) ?? ""));
14168
15453
 
14169
- if ($targetSection.length < 1) return false;
15454
+ if ($targetSection.length < 1) {
15455
+ if (instanceOrigin != null) return false;
15456
+ $targetSection = this.$blindSections.filter(eid + id);
15457
+ if ($targetSection.length < 1) return false;
15458
+ $targetSection = $($targetSection[$targetSection.length - 1]);
15459
+ }
14170
15460
 
14171
15461
  const isModal = $targetSection.hasClass("modal");
14172
15462
 
@@ -14184,7 +15474,7 @@ const estreUi = {
14184
15474
 
14185
15475
  const currentTopHandle = this.blindedCurrentOnTop;
14186
15476
  const currentTopHandleId = currentTopHandle?.id;
14187
- if (id != currentTopHandleId && currentTopHandleId != this.prevBlindedId) {
15477
+ if (id != currentTopHandleId && currentTopHandleId != this.latestBlindedId) {
14188
15478
  this.prevBlindedId = currentTopHandleId;
14189
15479
 
14190
15480
  // if (estreUi.euiState == "onReady" && currentTopHandle != null) {
@@ -14193,8 +15483,13 @@ const estreUi = {
14193
15483
  }
14194
15484
  }
14195
15485
 
14196
- const targetComponent = this.blindSections[id];
14197
- if (targetComponent == null) return false;
15486
+ let targetComponent = this.blindSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15487
+ if (targetComponent == null) {
15488
+ if (instanceOrigin != null) return false;
15489
+ const componentIds = this.blindSections.ways.filter(it => it.startsWith(id + "^"));
15490
+ if (componentIds.length < 1) return false;
15491
+ targetComponent = this.blindSections[componentIds[componentIds.length - 1]];
15492
+ }
14198
15493
  targetComponent.pushIntent(intent);
14199
15494
  if (targetComponent.isOnTop) {
14200
15495
  unhandled = true;
@@ -14206,9 +15501,14 @@ const estreUi = {
14206
15501
  return !unhandled;
14207
15502
  },
14208
15503
 
14209
- async closeInstantBlinded(id) {
14210
- const component = this.blindSections[id];
14211
- if (component == null) return null;
15504
+ async closeInstantBlinded(id, instanceOrigin, isTermination = !component.isStatic) {
15505
+ let component = this.blindSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15506
+ if (component == null) {
15507
+ if (instanceOrigin != null) return null;
15508
+ const componentIds = this.blindSections.ways.filter(it => it.startsWith(id + "^"));
15509
+ if (componentIds.length < 1) return null;
15510
+ component = this.blindSections[componentIds[componentIds.length - 1]];
15511
+ }
14212
15512
  const $targetSection = component.$host;
14213
15513
  const isModal = $targetSection.hasClass("modal");
14214
15514
 
@@ -14220,7 +15520,6 @@ const estreUi = {
14220
15520
  } else return null;
14221
15521
  } else {
14222
15522
  if (!component.$host.hasClass("home")) {
14223
- const isTermination = !component.isStatic;
14224
15523
  const closed = await component.close(false, isTermination);
14225
15524
  setTimeout(async _ => {
14226
15525
  const $components = this.$blindSections.filter(naiv(m.id, id));
@@ -14236,22 +15535,27 @@ const estreUi = {
14236
15535
  }
14237
15536
  },
14238
15537
 
14239
- openMenuArea(id, intent) {
15538
+ openMenuArea(id, intent, instanceOrigin) {
14240
15539
  const page = pageManager.getComponent(id);
14241
15540
  if (page == null) return null;
14242
15541
  if (page.statement == "static") return null;
14243
15542
  this.$mainMenu.append(page.live);
14244
15543
  const $section = this.$menuSections.filter(eid + id);
14245
15544
  if ($section == null || $section.length < 1) return null;
14246
- const component = this.initStaticMenu($section[0], intent);
15545
+ const component = this.initStaticMenu($section[$section.length - 1], intent, instanceOrigin);
14247
15546
  if (component.isOnTop) component.show(false);
14248
15547
  return component;
14249
15548
  },
14250
15549
 
14251
- showMenuArea(id, intent) {
14252
- const $targetSection = this.$menuSections.filter(eid + id);
15550
+ showMenuArea(id, intent, instanceOrigin) {
15551
+ let $targetSection = this.$menuSections.filter(eid + id + (instanceOrigin?.let(it => aiv(eds.instanceOrigin, it)) ?? ""));
14253
15552
 
14254
- if ($targetSection.length < 1) return false;
15553
+ if ($targetSection.length < 1) {
15554
+ if (instanceOrigin != null) return false;
15555
+ $targetSection = this.$menuSections.filter(eid + id);
15556
+ if ($targetSection.length < 1) return false;
15557
+ $targetSection = $($targetSection[$targetSection.length - 1]);
15558
+ }
14255
15559
 
14256
15560
  const isModal = $targetSection.hasClass("modal");
14257
15561
 
@@ -14268,8 +15572,13 @@ const estreUi = {
14268
15572
  for (var section of $elseSections) section.pageHandle?.hide(false);
14269
15573
  }
14270
15574
 
14271
- const targetComponent = this.menuSections[id];
14272
- if (targetComponent == null) return false;
15575
+ let targetComponent = this.menuSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15576
+ if (targetComponent == null) {
15577
+ if (instanceOrigin != null) return false;
15578
+ const componentIds = this.menuSections.ways.filter(it => it.startsWith(id + "^"));
15579
+ if (componentIds.length < 1) return false;
15580
+ targetComponent = this.menuSections[componentIds[componentIds.length - 1]];
15581
+ }
14273
15582
  targetComponent.pushIntent(intent);
14274
15583
  if (targetComponent.isOnTop) {
14275
15584
  unhandled = true;
@@ -14283,9 +15592,14 @@ const estreUi = {
14283
15592
  return !unhandled;
14284
15593
  },
14285
15594
 
14286
- async closeMenuArea(id) {
14287
- const component = this.menuSections[id];
14288
- if (component == null) return null;
15595
+ async closeMenuArea(id, instanceOrigin, isTermination) {
15596
+ let component = this.menuSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15597
+ if (component == null) {
15598
+ if (instanceOrigin != null) return null;
15599
+ const componentIds = this.menuSections.ways.filter(it => it.startsWith(id + "^"));
15600
+ if (componentIds.length < 1) return null;
15601
+ component = this.menuSections[componentIds[componentIds.length - 1]];
15602
+ }
14289
15603
  const $targetSection = component.$host;
14290
15604
  const isModal = $targetSection.hasClass("modal");
14291
15605
 
@@ -14296,29 +15610,34 @@ const estreUi = {
14296
15610
  return closed;
14297
15611
  } else return null;
14298
15612
  } else {
14299
- const isTermination = !component.isStatic;
15613
+ isTermination ??= !component.isStatic;
14300
15614
  const closed = await component.close(false, isTermination);
14301
15615
  if (isTermination) await this.releaseInstantContent(component);
14302
15616
  return closed;
14303
15617
  }
14304
15618
  },
14305
15619
 
14306
- openHeaderBar(id, intent) {
15620
+ openHeaderBar(id, intent, instanceOrigin) {
14307
15621
  const page = pageManager.getComponent(id);
14308
15622
  if (page == null) return null;
14309
15623
  if (page.statement == "static") return null;
14310
15624
  this.$headerArea.append(page.live);
14311
15625
  const $section = this.$headerSections.filter(eid + id);
14312
15626
  if ($section == null || $section.length < 1) return null;
14313
- const component = this.initHeaderBar($section[0], intent);
15627
+ const component = this.initHeaderBar($section[$section.length - 1], intent, instanceOrigin);
14314
15628
  // if (component.isOnTop) component.show(false);
14315
15629
  return component;
14316
15630
  },
14317
15631
 
14318
- showHeaderBar(id, intent) {
14319
- const $targetSection = this.$headerSections.filter(eid + id);
15632
+ showHeaderBar(id, intent, instanceOrigin) {
15633
+ let $targetSection = this.$headerSections.filter(eid + id + (instanceOrigin?.let(it => aiv(eds.instanceOrigin, it)) ?? ""));
14320
15634
 
14321
- if ($targetSection.length < 1) return false;
15635
+ if ($targetSection.length < 1) {
15636
+ if (instanceOrigin != null) return false;
15637
+ $targetSection = this.$headerSections.filter(eid + id);
15638
+ if ($targetSection.length < 1) return false;
15639
+ $targetSection = $($targetSection[$targetSection.length - 1]);
15640
+ }
14322
15641
 
14323
15642
  const isModal = $targetSection.hasClass("modal");
14324
15643
 
@@ -14335,8 +15654,13 @@ const estreUi = {
14335
15654
  for (var section of $elseSections) section.pageHandle?.hide(false);
14336
15655
  }
14337
15656
 
14338
- const targetComponent = this.headerSections[id];
14339
- if (targetComponent == null) return false;
15657
+ let targetComponent = this.headerSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15658
+ if (targetComponent == null) {
15659
+ if (instanceOrigin != null) return false;
15660
+ const componentIds = this.headerSections.ways.filter(it => it.startsWith(id + "^"));
15661
+ if (componentIds.length < 1) return false;
15662
+ targetComponent = this.headerSections[componentIds[componentIds.length - 1]];
15663
+ }
14340
15664
  targetComponent.pushIntent(intent);
14341
15665
  if (targetComponent.isOnTop) {
14342
15666
  unhandled = true;
@@ -14348,9 +15672,14 @@ const estreUi = {
14348
15672
  return !unhandled;
14349
15673
  },
14350
15674
 
14351
- async closeHeaderBar(id) {
14352
- const component = this.headerSections[id];
14353
- if (component == null) return null;
15675
+ async closeHeaderBar(id, instanceOrigin, isTermination) {
15676
+ let component = this.headerSections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15677
+ if (component == null) {
15678
+ if (instanceOrigin != null) return null;
15679
+ const componentIds = this.headerSections.ways.filter(it => it.startsWith(id + "^"));
15680
+ if (componentIds.length < 1) return null;
15681
+ component = this.headerSections[componentIds[componentIds.length - 1]];
15682
+ }
14354
15683
  const $targetSection = component.$host;
14355
15684
  const isModal = $targetSection.hasClass("modal");
14356
15685
 
@@ -14361,29 +15690,34 @@ const estreUi = {
14361
15690
  return closed;
14362
15691
  } else return null;
14363
15692
  } else {
14364
- const isTermination = !component.isStatic;
15693
+ isTermination ??= !component.isStatic;
14365
15694
  const closed = await component.close(false, isTermination);
14366
15695
  if (isTermination) await this.releaseInstantContent(component);
14367
15696
  return closed;
14368
15697
  }
14369
15698
  },
14370
15699
 
14371
- openManagedOverlay(id, intent) {
15700
+ openManagedOverlay(id, intent, instanceOrigin) {
14372
15701
  const page = pageManager.getComponent(id, "overlay");
14373
15702
  if (page == null) return null;
14374
15703
  if (page.statement == "static") return null;
14375
15704
  this.$overlayArea.append(page.live);
14376
15705
  const $section = this.$overlaySections.filter(eid + id);
14377
15706
  if ($section == null || $section.length < 1) return null;
14378
- const component = this.initOverlayContent($section[0], intent);
15707
+ const component = this.initOverlayContent($section[$section.length - 1], intent, instanceOrigin);
14379
15708
  // if (component.isOnTop) component.show(false);
14380
15709
  return component;
14381
15710
  },
14382
15711
 
14383
- showManagedOverlay(id, intent) {
14384
- const $targetSection = this.$overlaySections.filter(eid + id);
15712
+ showManagedOverlay(id, intent, instanceOrigin) {
15713
+ let $targetSection = this.$overlaySections.filter(eid + id + (instanceOrigin?.let(it => aiv(eds.instanceOrigin, it)) ?? ""));
14385
15714
 
14386
- if ($targetSection.length < 1) return false;
15715
+ if ($targetSection.length < 1) {
15716
+ if (instanceOrigin != null) return false;
15717
+ $targetSection = this.$overlaySections.filter(eid + id);
15718
+ if ($targetSection.length < 1) return false;
15719
+ $targetSection = $($targetSection[$targetSection.length - 1]);
15720
+ }
14387
15721
 
14388
15722
  const isModal = $targetSection.hasClass("modal");
14389
15723
 
@@ -14400,8 +15734,13 @@ const estreUi = {
14400
15734
  for (var section of $elseSections) section.pageHandle?.hide(false);
14401
15735
  }
14402
15736
 
14403
- const targetComponent = this.overlaySections[id];
14404
- if (targetComponent == null) return false;
15737
+ let targetComponent = this.overlaySections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15738
+ if (targetComponent == null) {
15739
+ if (instanceOrigin != null) return false;
15740
+ const componentIds = this.overlaySections.ways.filter(it => it.startsWith(id + "^"));
15741
+ if (componentIds.length < 1) return false;
15742
+ targetComponent = this.overlaySections[componentIds[componentIds.length - 1]];
15743
+ }
14405
15744
  targetComponent.pushIntent(intent);
14406
15745
  if (targetComponent.isOnTop) {
14407
15746
  unhandled = true;
@@ -14413,9 +15752,14 @@ const estreUi = {
14413
15752
  return !unhandled;
14414
15753
  },
14415
15754
 
14416
- async closeManagedOverlay(id) {
14417
- const component = this.overlaySections[id];
14418
- if (component == null) return null;
15755
+ async closeManagedOverlay(id, instanceOrigin, isTermination) {
15756
+ let component = this.overlaySections[id + (instanceOrigin?.let(it => "^" + it) ?? "")];
15757
+ if (component == null) {
15758
+ if (instanceOrigin != null) return null;
15759
+ const componentIds = this.overlaySections.ways.filter(it => it.startsWith(id + "^"));
15760
+ if (componentIds.length < 1) return null;
15761
+ component = this.overlaySections[componentIds[componentIds.length - 1]];
15762
+ }
14419
15763
  const $targetSection = component.$host;
14420
15764
  const isModal = $targetSection.hasClass("modal");
14421
15765
 
@@ -14426,7 +15770,7 @@ const estreUi = {
14426
15770
  return closed;
14427
15771
  } else return null;
14428
15772
  } else {
14429
- const isTermination = !component.isStatic;
15773
+ isTermination ??= !component.isStatic;
14430
15774
  const closed = await component.close(false, isTermination);
14431
15775
  if (isTermination) await this.releaseInstantContent(component);
14432
15776
  return closed;
@@ -14503,7 +15847,7 @@ const estreUi = {
14503
15847
 
14504
15848
  const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
14505
15849
  for (var i=0; i<$oss.length; i++) {
14506
- this.initOverlayContent($oss[i], null, true);
15850
+ this.initOverlayContent($oss[i], null, u, true);
14507
15851
  await delayer();
14508
15852
  }
14509
15853
 
@@ -14514,17 +15858,18 @@ const estreUi = {
14514
15858
 
14515
15859
  releaseOverlayContent(component) {
14516
15860
  if (component == null) return;
15861
+ const instanceId = component.instanceId;
14517
15862
  component.release(component.isStatic ? null : true);
14518
- if (this.blindSections[component.id] != null) delete this.overlaySections[component.id];
15863
+ if (this.blindSections[instanceId] != null) delete this.overlaySections[instanceId];
14519
15864
  const index = this.overlaySectionList.indexOf(component);
14520
15865
  if (index > -1) this.overlaySectionList.splice(index, 1);
14521
15866
  },
14522
15867
 
14523
- initOverlayContent(bound, intent = null, init = false) {
15868
+ initOverlayContent(bound, intent = null, instanceOrigin, init = false) {
14524
15869
  this.releaseOverlayContent(bound.pageHandle);
14525
- const component = new EstreOverlayComponent(bound);
15870
+ const component = new EstreOverlayComponent(bound, instanceOrigin);
14526
15871
  if (!init || component.isStatic) {
14527
- this.overlaySections[component.id] = component;
15872
+ this.overlaySections[component.instanceId] = component;
14528
15873
  this.overlaySectionList.push(component);
14529
15874
  }
14530
15875
  component.init(intent);
@@ -14537,7 +15882,7 @@ const estreUi = {
14537
15882
 
14538
15883
  const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
14539
15884
  for (var i=0; i<$bss.length; i++) {
14540
- this.initInstantContent($bss[i], null, true);
15885
+ this.initInstantContent($bss[i], null, u, true);
14541
15886
  await delayer();
14542
15887
  }
14543
15888
 
@@ -14552,17 +15897,18 @@ const estreUi = {
14552
15897
 
14553
15898
  releaseInstantContent(component) {
14554
15899
  if (component == null) return;
15900
+ const instanceId = component.instanceId;
14555
15901
  component.release(component.isStatic ? null : true);
14556
- if (this.blindSections[component.id] != null) delete this.blindSections[component.id];
15902
+ if (this.blindSections[instanceId] != null) delete this.blindSections[instanceId];
14557
15903
  const index = this.blindSectionList.indexOf(component);
14558
15904
  if (index > -1) this.blindSectionList.splice(index, 1);
14559
15905
  },
14560
15906
 
14561
- initInstantContent(bound, intent = null, init = false) {
15907
+ initInstantContent(bound, intent = null, instanceOrigin, init = false) {
14562
15908
  this.releaseInstantContent(bound.pageHandle);
14563
- const component = new EstreInstantComponent(bound);
15909
+ const component = new EstreInstantComponent(bound, instanceOrigin);
14564
15910
  if (!init || component.isStatic) {
14565
- this.blindSections[component.id] = component;
15911
+ this.blindSections[component.instanceId] = component;
14566
15912
  this.blindSectionList.push(component);
14567
15913
  }
14568
15914
  component.init(intent);
@@ -14575,7 +15921,7 @@ const estreUi = {
14575
15921
 
14576
15922
  const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
14577
15923
  for (var i=0; i<$mss.length; i++) {
14578
- this.initStaticContent($mss[i], null, true);
15924
+ this.initStaticContent($mss[i], null, u, true);
14579
15925
  await delayer();
14580
15926
  }
14581
15927
 
@@ -14592,17 +15938,18 @@ const estreUi = {
14592
15938
 
14593
15939
  releaseStaticContent(component) {
14594
15940
  if (component == null) return;
15941
+ const instanceId = component.instanceId;
14595
15942
  component.release(component.isStatic ? null : true);
14596
- if (this.mainSections[component.id] != null) delete this.mainSections[component.id];
15943
+ if (this.mainSections[instanceId] != null) delete this.mainSections[instanceId];
14597
15944
  const index = this.mainSectionList.indexOf(component);
14598
15945
  if (index > -1) this.mainSectionList.splice(index, 1);
14599
15946
  },
14600
15947
 
14601
- initStaticContent(bound, intent = null, init = false) {
15948
+ initStaticContent(bound, intent = null, instanceOrigin, init = false) {
14602
15949
  this.releaseStaticContent(bound.pageHandle);
14603
- const component = new EstreComponent(bound);
15950
+ const component = new EstreComponent(bound, instanceOrigin);
14604
15951
  if (!init || component.isStatic) {
14605
- this.mainSections[component.id] = component;
15952
+ this.mainSections[component.instanceId] = component;
14606
15953
  this.mainSectionList.push(component);
14607
15954
  }
14608
15955
  component.init(intent);
@@ -14617,7 +15964,7 @@ const estreUi = {
14617
15964
 
14618
15965
  const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
14619
15966
  for (var i=0; i<$mss.length; i++) {
14620
- this.initStaticMenu($mss[i], null, true);
15967
+ this.initStaticMenu($mss[i], null, u, true);
14621
15968
  await delayer();
14622
15969
  }
14623
15970
 
@@ -14632,17 +15979,18 @@ const estreUi = {
14632
15979
 
14633
15980
  releaseStaticMenu(component) {
14634
15981
  if (component == null) return;
15982
+ const instanceId = component.instanceId;
14635
15983
  component.release(component.isStatic ? null : true);
14636
- if (this.menuSections[component.id] != null) delete this.menuSections[component.id];
15984
+ if (this.menuSections[instanceId] != null) delete this.menuSections[instanceId];
14637
15985
  const index = this.menuSectionList.indexOf(component);
14638
15986
  if (index > -1) this.menuSectionList.splice(index, 1);
14639
15987
  },
14640
15988
 
14641
- initStaticMenu(bound, intent = null, init = false) {
15989
+ initStaticMenu(bound, intent = null, instanceOrigin, init = false) {
14642
15990
  this.releaseStaticMenu(bound.pageHandle);
14643
- const component = new EstreMenuComponent(bound);
15991
+ const component = new EstreMenuComponent(bound, instanceOrigin);
14644
15992
  if (!init || component.isStatic) {
14645
- this.menuSections[component.id] = component;
15993
+ this.menuSections[component.instanceId] = component;
14646
15994
  this.menuSectionList.push(component);
14647
15995
  }
14648
15996
  component.init(intent);
@@ -14655,7 +16003,7 @@ const estreUi = {
14655
16003
 
14656
16004
  const delayer = (delay = term) => postPromise(resolve => setTimeout(resolve, delay));
14657
16005
  for (var i=0; i<$hss.length; i++) {
14658
- this.initHeaderBar($hss[i], null, true);
16006
+ this.initHeaderBar($hss[i], null, u, true);
14659
16007
  await delayer();
14660
16008
  }
14661
16009
 
@@ -14671,17 +16019,18 @@ const estreUi = {
14671
16019
 
14672
16020
  releaseHeaderBar(component) {
14673
16021
  if (component == null) return;
16022
+ const instanceId = component.instanceId;
14674
16023
  component.release(component.isStatic ? null : true);
14675
- if (this.headerSections[component.id] != null) delete this.headerSections[component.id];
16024
+ if (this.headerSections[instanceId] != null) delete this.headerSections[instanceId];
14676
16025
  const index = this.headerSectionList.indexOf(component);
14677
16026
  if (index > -1) this.headerSectionList.splice(index, 1);
14678
16027
  },
14679
16028
 
14680
- initHeaderBar(bound, intent = null, init = false) {
16029
+ initHeaderBar(bound, intent = null, instanceOrigin, init = false) {
14681
16030
  this.releaseHeaderBar(bound.pageHandle);
14682
- const component = new EstreHeaderComponent(bound);
16031
+ const component = new EstreHeaderComponent(bound, instanceOrigin);
14683
16032
  if (!init || component.isStatic) {
14684
- this.headerSections[component.id] = component;
16033
+ this.headerSections[component.instanceId] = component;
14685
16034
  this.headerSectionList.push(component);
14686
16035
  }
14687
16036
  component.init(intent);
@@ -14823,9 +16172,9 @@ const estreUi = {
14823
16172
  const currentOnTop = this.blindedCurrentOnTop;
14824
16173
  let processed = false;
14825
16174
  if (currentOnTop != null) processed = await currentOnTop.onBack();
14826
- if (!processed && this.prevBlindedId != null) {
14827
- processed = await this.showInstantBlinded(this.prevBlindedId);
14828
- if (processed) this.prevBlindedId = null;
16175
+ const prevBlindedId = this.prevBlindedId;
16176
+ if (!processed && prevBlindedId != null) {
16177
+ processed = await this.showInstantBlinded(prevBlindedId);
14829
16178
  }
14830
16179
  return processed;
14831
16180
  },