@inappstory/slide-api 0.0.21 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -573,8 +573,8 @@ const getWinWidth = function (env) {
573
573
  const getWinHeight = function (env) {
574
574
  return env.innerHeight || env.document.documentElement.clientHeight || env.document.body.clientHeight;
575
575
  };
576
- const sendStatisticEventToApp = function (sdkApi, name, data, devPayload) {
577
- sdkApi.sendStatisticEvent(name, data, devPayload);
576
+ const sendStatisticEventToApp = function (sdkApi, name, data, devPayload, options) {
577
+ sdkApi.sendStatisticEvent(name, data, devPayload, options?.forceEnableStatisticV2 ?? false);
578
578
  };
579
579
  const getValueOrException = function (value, message) {
580
580
  if (value == null) {
@@ -670,6 +670,37 @@ const Clipboard = (function (window, document, navigator) {
670
670
  copy,
671
671
  };
672
672
  })(window, document, navigator);
673
+ function FilterNumber(x) {
674
+ return typeof x === "number";
675
+ }
676
+ function determineLocale() {
677
+ // All modern browsers support this. Should match what's used by localeCompare() etc.
678
+ const intl = window.Intl;
679
+ if (intl !== undefined) {
680
+ return intl.NumberFormat().resolvedOptions().locale;
681
+ }
682
+ // Fall back to ranked choice locales, which are configured in the browser but aren't necessarily
683
+ // what's used in functions like localeCompare().
684
+ const languages = navigator.languages;
685
+ if (languages !== undefined && languages.length > 0) {
686
+ return languages[0];
687
+ }
688
+ // Old standard.
689
+ return navigator.language ?? "en-US";
690
+ }
691
+ function isScreenSupportsTouch(env) {
692
+ let supportsTouch = false;
693
+ if ("ontouchstart" in env) {
694
+ supportsTouch = true;
695
+ }
696
+ else if (env.navigator.msPointerEnabled) {
697
+ supportsTouch = true;
698
+ }
699
+ else if ("ontouchstart" in env.document.documentElement) {
700
+ supportsTouch = true;
701
+ }
702
+ return supportsTouch;
703
+ }
673
704
 
674
705
  var supportAnimate = document.documentElement.animate !== undefined;
675
706
  supportAnimate = false; // tmp off
@@ -1067,8 +1098,8 @@ class EsModuleSdkApi {
1067
1098
  showNextSlide(duration) {
1068
1099
  this.sdkBinding().showNextSlide(duration);
1069
1100
  }
1070
- sendStatisticEvent(name, data, devPayload) {
1071
- this.sdkBinding().sendStatisticEvent(name, data, devPayload);
1101
+ sendStatisticEvent(name, data, devPayload, forceEnableStatisticV2) {
1102
+ this.sdkBinding().sendStatisticEvent(name, data, devPayload, forceEnableStatisticV2);
1072
1103
  }
1073
1104
  getCardLocalData() {
1074
1105
  return this.sdkBinding().getCardLocalData();
@@ -1169,6 +1200,14 @@ class EsModuleSdkApi {
1169
1200
  getCardFonts() {
1170
1201
  return this.sdkBinding().getCardFonts();
1171
1202
  }
1203
+ disableVerticalSwipeGesture() {
1204
+ this.sdkBinding().disableVerticalSwipeGesture();
1205
+ }
1206
+ enableVerticalSwipeGesture() {
1207
+ this.sdkBinding().enableVerticalSwipeGesture();
1208
+ }
1209
+ disableBackpress() { }
1210
+ enableBackpress() { }
1172
1211
  static get [Symbol.for("___CTOR_ARGS___")]() { return [`() => SDKInterface`]; }
1173
1212
  }
1174
1213
 
@@ -1200,6 +1239,8 @@ class WidgetBase {
1200
1239
  localData = null;
1201
1240
  firstOpenTime = 0;
1202
1241
  id;
1242
+ startReadyPromise = null;
1243
+ startReadyResolve = null;
1203
1244
  constructor(element, options, elementIdGetter, slideGetter) {
1204
1245
  this.options = extend({}, this.constructor.DEFAULTS, options);
1205
1246
  this.element = element;
@@ -1251,12 +1292,32 @@ class WidgetBase {
1251
1292
  this.localData = extend({}, this.savedData ?? {}, this.options.localData ?? {});
1252
1293
  this.id = `w_${this.elementId}_${WidgetBase.widgetIndex}`;
1253
1294
  ++WidgetBase.widgetIndex;
1295
+ this.resetStartReadyPromise();
1296
+ }
1297
+ resetStartReadyPromise() {
1298
+ this.startReadyPromise = new Promise(resolve => {
1299
+ this.startReadyResolve = resolve;
1300
+ });
1254
1301
  }
1255
1302
  /**
1256
1303
  * Start or restart widget
1257
1304
  * @param localData
1258
1305
  */
1259
- onRefreshUserData(localData) { }
1306
+ onRefreshUserData(localData) {
1307
+ this.savedData = this.sdkApi.getCardServerData(this.cardId);
1308
+ this.localData = extend({}, this.savedData ?? {}, localData);
1309
+ }
1310
+ onStart() {
1311
+ // add active class for enable animation
1312
+ this.element.classList.add("active");
1313
+ this.startReadyResolve();
1314
+ }
1315
+ onStop() {
1316
+ this.element.classList.remove("active");
1317
+ this.resetStartReadyPromise();
1318
+ }
1319
+ onPause() { }
1320
+ onResume() { }
1260
1321
  static widgetCacheKey = "ias.story-element";
1261
1322
  static widgetClassName = "";
1262
1323
  static getInstance(element) {
@@ -1401,16 +1462,16 @@ class WidgetBase {
1401
1462
  }
1402
1463
  return data;
1403
1464
  }
1404
- static sendStatisticEventToApp(name, data, devPayload) {
1405
- sendStatisticEventToApp(this.widgetsService.sdkApi, name, data, devPayload);
1465
+ static sendStatisticEventToApp(name, data, devPayload, options) {
1466
+ sendStatisticEventToApp(this.widgetsService.sdkApi, name, data, devPayload, options);
1406
1467
  }
1407
- sendStatisticEventToApp(name, data, devPayload) {
1408
- this.constructor.sendStatisticEventToApp(name, data, devPayload);
1468
+ sendStatisticEventToApp(name, data, devPayload, options) {
1469
+ this.constructor.sendStatisticEventToApp(name, data, devPayload, options);
1409
1470
  }
1410
1471
  startDisabledTimeline() {
1411
1472
  this.sdkApi.startDisabledTimeline(this.cardId, this.slideIndex);
1412
1473
  }
1413
- _showLayout(layers, selectIndex, withStatEvent = false) {
1474
+ _showLayer(layers, selectIndex, withStatEvent = false) {
1414
1475
  if (this.sdkApi.isExistsShowLayer()) {
1415
1476
  this.sdkApi.showLayer(selectIndex);
1416
1477
  }
@@ -1553,9 +1614,21 @@ class WidgetCopy extends WidgetBase {
1553
1614
  * @param localData
1554
1615
  */
1555
1616
  onRefreshUserData(localData) {
1556
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
1557
- this.localData = extend({}, this.savedData ?? {}, localData);
1617
+ super.onRefreshUserData(localData);
1618
+ // return DOM to init state (ready to copy)
1619
+ this.element.classList.remove("done");
1620
+ if (this.resultLayer) {
1621
+ this.resultLayer.classList.remove("done");
1622
+ }
1558
1623
  this.state = null;
1624
+ if (this.isPromotionalCode) {
1625
+ this.initPromotionalCodeFromLocalData();
1626
+ }
1627
+ }
1628
+ onStart() {
1629
+ super.onStart();
1630
+ // add active class for enable animation
1631
+ this.resultLayer?.classList.add("active");
1559
1632
  if (this.isPromotionalCode) {
1560
1633
  this.fetchPromoCode();
1561
1634
  }
@@ -1579,16 +1652,22 @@ class WidgetCopy extends WidgetBase {
1579
1652
  this.button.textContent = newText;
1580
1653
  }
1581
1654
  }
1582
- fetchPromoCode() {
1583
- this.state = 0;
1584
- if (this.localData["_cp_g_" + this.elementId + "_pc"] !== undefined) {
1655
+ getPromotionalCodeFromLocalData() {
1656
+ return this.localData["_cp_g_" + this.elementId + "_pc"];
1657
+ }
1658
+ initPromotionalCodeFromLocalData() {
1659
+ if (this.getPromotionalCodeFromLocalData() !== undefined) {
1585
1660
  this.state = 1;
1586
- this.clipboardTarget = this.localData["_cp_g_" + this.elementId + "_pc"];
1661
+ this.clipboardTarget = this.getPromotionalCodeFromLocalData();
1587
1662
  if (this.clipboardTarget != null) {
1588
1663
  this.changeText(this.clipboardTarget);
1589
1664
  }
1590
1665
  removeClass(this.element, "loader");
1591
1666
  }
1667
+ }
1668
+ fetchPromoCode() {
1669
+ this.state = 0;
1670
+ this.initPromotionalCodeFromLocalData();
1592
1671
  if (this.state === 0) {
1593
1672
  if (!this.isTransparentElement()) {
1594
1673
  // for transparent element
@@ -1676,12 +1755,14 @@ class WidgetCopy extends WidgetBase {
1676
1755
  if (this.resultLayer) {
1677
1756
  this.resultLayer.classList.add("done");
1678
1757
  }
1679
- if (this.disableTimer) {
1680
- // флаг - что таймер уже стартанул (в layout или добавить объект sharedMemory)
1681
- // смотрим что прозрачный текст - тогда и лоадер прозрачный
1682
- // _log("_showNarrativeNextSlide: " + getSlideDuration(this.narrativeId, this.slideIndex), true);
1683
- this.startDisabledTimeline();
1684
- }
1758
+ this.startReadyPromise.then(() => {
1759
+ if (this.disableTimer) {
1760
+ // флаг - что таймер уже стартанул layout или добавить объект sharedMemory)
1761
+ // смотрим что прозрачный текст - тогда и лоадер прозрачный
1762
+ // _log("_showNarrativeNextSlide: " + getSlideDuration(this.narrativeId, this.slideIndex), true);
1763
+ this.startDisabledTimeline();
1764
+ }
1765
+ });
1685
1766
  }
1686
1767
  copyToClipboard(element) {
1687
1768
  this._select();
@@ -1715,6 +1796,13 @@ class WidgetCopy extends WidgetBase {
1715
1796
  // prevent initWidget for result layer
1716
1797
  const elements = slice.call(nodeList).filter(element => !element.classList.contains("narrative-element-copy-result-variant"));
1717
1798
  WidgetCopy.initWidgets((element, options) => new WidgetCopy(element, options), elements, localData);
1799
+ elements.forEach(element => WidgetCopy.getInstance(element)?.onStart());
1800
+ },
1801
+ onStart: function (element) {
1802
+ WidgetCopy.getInstance(element)?.onStart();
1803
+ },
1804
+ onStop: function (element) {
1805
+ WidgetCopy.getInstance(element)?.onStop();
1718
1806
  },
1719
1807
  click: function (element) {
1720
1808
  const widgetElement = element.closest(`.${WidgetCopy.widgetClassName}`);
@@ -1770,17 +1858,21 @@ class WidgetDataInput extends WidgetBase {
1770
1858
  * @param localData
1771
1859
  */
1772
1860
  onRefreshUserData(localData) {
1773
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
1774
- this.localData = extend({}, this.savedData ?? {}, localData);
1775
- const text = this.localData["_di_g_" + this.elementId + "_t"];
1861
+ super.onRefreshUserData(localData);
1862
+ const text = this.getTextFromLocalData();
1776
1863
  this._fillUserText(text);
1777
- if (text) {
1864
+ if (text != null) {
1778
1865
  this.element.classList.add("done");
1779
- if (this.disableTimer) {
1780
- this.startDisabledTimeline();
1781
- }
1866
+ this.startReadyPromise.then(() => {
1867
+ if (this.disableTimer) {
1868
+ this.startDisabledTimeline();
1869
+ }
1870
+ });
1782
1871
  }
1783
1872
  }
1873
+ getTextFromLocalData() {
1874
+ return this.localData["_di_g_" + this.elementId + "_t"];
1875
+ }
1784
1876
  _statEventFocusIn() {
1785
1877
  try {
1786
1878
  const labelText = this.label ? this.label.textContent ?? "" : "";
@@ -1858,7 +1950,7 @@ class WidgetDataInput extends WidgetBase {
1858
1950
  }
1859
1951
  _fillUserText(text) {
1860
1952
  if (this.inputElement && this.textElement) {
1861
- if (text) {
1953
+ if (text != null) {
1862
1954
  this.inputElement.classList.remove("_is-placeholder");
1863
1955
  text = text.replace(new RegExp("\r?\n", "g"), "<br />");
1864
1956
  this.textElement.innerHTML = text;
@@ -1908,7 +2000,15 @@ class WidgetDataInput extends WidgetBase {
1908
2000
  },
1909
2001
  /** @deprecated */
1910
2002
  initWidget: function (nodeList, localData) {
2003
+ const elements = slice.call(nodeList);
1911
2004
  WidgetDataInput.initWidgets((element, options) => new WidgetDataInput(element, options), slice.call(nodeList), localData);
2005
+ elements.forEach(element => WidgetDataInput.getInstance(element)?.onStart());
2006
+ },
2007
+ onStart: function (element) {
2008
+ WidgetDataInput.getInstance(element)?.onStart();
2009
+ },
2010
+ onStop: function (element) {
2011
+ WidgetDataInput.getInstance(element)?.onStop();
1912
2012
  },
1913
2013
  click: function (element) {
1914
2014
  const widgetElement = element.closest(`.${WidgetDataInput.widgetClassName}`);
@@ -1939,7 +2039,7 @@ class WidgetDateCountdown extends WidgetBase {
1939
2039
  label;
1940
2040
  layers;
1941
2041
  messages;
1942
- timestampSeconds;
2042
+ timestampMs;
1943
2043
  diff;
1944
2044
  timerInit;
1945
2045
  pendingUpdate;
@@ -1961,58 +2061,58 @@ class WidgetDateCountdown extends WidgetBase {
1961
2061
  minutes: getTagData(this.element, "tMinutes") ?? "",
1962
2062
  seconds: getTagData(this.element, "tSeconds") ?? "",
1963
2063
  };
1964
- this.timestampSeconds = getValueOrException(getTagDataAsNumber(this.element, "timestampSeconds"), "Empty timestampSeconds");
2064
+ this.timestampMs = getValueOrException(getTagDataAsNumber(this.element, "timestampSeconds"), "Empty timestampSeconds") * 1000;
1965
2065
  this.diff = 0;
1966
2066
  this.timerInit = false;
1967
2067
  this.pendingUpdate = true;
1968
2068
  this.layers = this.options.layers;
1969
- // if (false) {
1970
- // // if (sendApiRequestSupported()) {
1971
- // // fetch project time
1972
- // var path = "story/" + this.storyId + "/widget/" + this.elementId + "/timestamp";
1973
- // var profileKey = "fetch-story-timestamp";
1974
- // this.sdkApi
1975
- // .sendApiRequest<{ timestamp: number }>(path, "GET", null, null, null, profileKey)
1976
- // .then(response => {
1977
- // var status = response.status;
1978
- // var timestamp = null;
1979
- // if (status === 200) {
1980
- // if (response.data) timestamp = response.data.timestamp;
1981
- // if (timestamp) {
1982
- // this.diff = new Date().getTime() - timestamp * 1000;
1983
- // }
1984
- // }
1985
- //
1986
- // this.initTimer();
1987
- // })
1988
- // .catch( (reason)=> {
1989
- // console.error(reason);
1990
- // this.initTimer();
1991
- // });
1992
- // } else {
1993
- this.initTimer();
1994
- // }
1995
2069
  }
1996
2070
  /**
1997
2071
  * Start or restart widget
1998
2072
  * @param localData
1999
2073
  */
2000
2074
  onRefreshUserData(localData) {
2001
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
2002
- this.localData = extend({}, this.savedData ?? {}, localData);
2075
+ super.onRefreshUserData(localData);
2076
+ const value = this.timestampMs - (new Date().getTime() - this.diff);
2077
+ if (value > 0) {
2078
+ this._showLayer(this.layers, 0);
2079
+ }
2080
+ else {
2081
+ if (this.layers[1] != null) {
2082
+ this._showLayer(this.layers, 1);
2083
+ }
2084
+ }
2003
2085
  }
2004
- pause() {
2086
+ onPause() {
2087
+ super.onPause();
2005
2088
  if (this.timerInit) {
2006
2089
  this.pendingUpdate = false;
2007
2090
  }
2008
2091
  }
2009
- resume() {
2010
- if (this.timerInit) {
2092
+ onResume() {
2093
+ super.onResume();
2094
+ if (this.timerInit && !this.pendingUpdate) {
2011
2095
  this.pendingUpdate = true;
2012
2096
  this.updateTimer();
2013
2097
  }
2014
2098
  }
2099
+ onStart() {
2100
+ super.onStart();
2101
+ if (!this.timerInit) {
2102
+ this.initTimer();
2103
+ }
2104
+ }
2105
+ onStop() {
2106
+ super.onStop();
2107
+ if (this.timerInit) {
2108
+ this.pendingUpdate = false;
2109
+ this.timerInit = false;
2110
+ }
2111
+ }
2015
2112
  initTimer() {
2113
+ if (this.timerInit) {
2114
+ return;
2115
+ }
2016
2116
  // find groups
2017
2117
  this.firstGroup1 = getValueOrException(this.element.querySelector(".date-item-view-group-1 .date-output-label-1"), "Empty firstGroup1");
2018
2118
  this.firstGroup2 = getValueOrException(this.element.querySelector(".date-item-view-group-1 .date-output-label-2"), "Empty firstGroup2");
@@ -2023,16 +2123,18 @@ class WidgetDateCountdown extends WidgetBase {
2023
2123
  this.thirdGroup1 = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-output-label-1"), "Empty thirdGroup1");
2024
2124
  this.thirdGroup2 = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-output-label-2"), "Empty thirdGroup2");
2025
2125
  this.thirdGroupCaption = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-item-caption"), "Empty thirdGroupCaption");
2026
- this.timestampSeconds *= 1000;
2027
2126
  this.timerInit = true;
2028
- const value = this.timestampSeconds - (new Date().getTime() - this.diff);
2127
+ const value = this.timestampMs - (new Date().getTime() - this.diff);
2029
2128
  if (value > 0) {
2030
- this._showLayout(this.layers, 0);
2129
+ this._showLayer(this.layers, 0);
2031
2130
  }
2032
2131
  this.updateTimer();
2033
2132
  }
2034
2133
  updateTimer() {
2035
- const value = this.timestampSeconds - (new Date().getTime() - this.diff);
2134
+ if (!this.timerInit) {
2135
+ return;
2136
+ }
2137
+ const value = this.timestampMs - (new Date().getTime() - this.diff);
2036
2138
  if (value > 0) {
2037
2139
  const result = this._asDuration(Math.round(value / 1000));
2038
2140
  if (result.days) {
@@ -2061,7 +2163,9 @@ class WidgetDateCountdown extends WidgetBase {
2061
2163
  }
2062
2164
  else {
2063
2165
  this.pendingUpdate = false;
2064
- this._showLayout(this.layers, 1);
2166
+ if (this.layers[1] != null) {
2167
+ this._showLayer(this.layers, 1);
2168
+ }
2065
2169
  }
2066
2170
  if (this.pendingUpdate) {
2067
2171
  this.env.requestAnimationFrame(() => this.updateTimer());
@@ -2134,24 +2238,32 @@ class WidgetDateCountdown extends WidgetBase {
2134
2238
  },
2135
2239
  /** @deprecated */
2136
2240
  initWidget: function (nodeList, layers, localData) {
2137
- WidgetDateCountdown.initWidgets((element, options) => new WidgetDateCountdown(element, { ...options, layers }), slice.call(nodeList), localData);
2241
+ const elements = slice.call(nodeList);
2242
+ WidgetDateCountdown.initWidgets((element, options) => new WidgetDateCountdown(element, { ...options, layers }), elements, localData);
2243
+ elements.forEach(element => WidgetDateCountdown.getInstance(element)?.onStart());
2244
+ },
2245
+ onStart: function (element) {
2246
+ WidgetDateCountdown.getInstance(element)?.onStart();
2247
+ },
2248
+ onStop: function (element) {
2249
+ WidgetDateCountdown.getInstance(element)?.onStop();
2138
2250
  },
2139
2251
  onPause: function (element) {
2140
- WidgetDateCountdown.getInstance(element)?.pause();
2252
+ WidgetDateCountdown.getInstance(element)?.onPause();
2141
2253
  },
2142
2254
  onResume: function (element) {
2143
- WidgetDateCountdown.getInstance(element)?.resume();
2255
+ WidgetDateCountdown.getInstance(element)?.onResume();
2144
2256
  },
2145
2257
  /** @deprecated */
2146
2258
  pause: function (nodeList) {
2147
2259
  forEach(slice.call(nodeList), function (el, index) {
2148
- WidgetDateCountdown.getInstance(el)?.pause();
2260
+ WidgetDateCountdown.getInstance(el)?.onPause();
2149
2261
  });
2150
2262
  },
2151
2263
  /** @deprecated */
2152
2264
  resume: function (nodeList) {
2153
2265
  forEach(slice.call(nodeList), function (el, index) {
2154
- WidgetDateCountdown.getInstance(el)?.resume();
2266
+ WidgetDateCountdown.getInstance(el)?.onResume();
2155
2267
  });
2156
2268
  },
2157
2269
  };
@@ -2343,8 +2455,7 @@ class WidgetPoll extends WidgetBase {
2343
2455
  * @param localData
2344
2456
  */
2345
2457
  onRefreshUserData(localData) {
2346
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
2347
- this.localData = extend({}, this.savedData ?? {}, localData);
2458
+ super.onRefreshUserData(localData);
2348
2459
  this.selectedVariant = undefined;
2349
2460
  if (this.localData) {
2350
2461
  if (this.localData["_p_g_" + this.elementId + "_sa"] !== undefined) {
@@ -2427,14 +2538,11 @@ class WidgetPoll extends WidgetBase {
2427
2538
  this.element.classList.add("with-total-result");
2428
2539
  this.displayPercents(index, filled);
2429
2540
  }
2430
- if (this.disableTimer) {
2431
- this.env.setTimeout(() => {
2432
- // todo poll - если виджет на первом слайде то при повторном заходе автоматически не стартует таймлайн слайда
2433
- // только в web sdk такое
2434
- // если поставить через setTimeout то все ок
2541
+ this.startReadyPromise.then(() => {
2542
+ if (this.disableTimer) {
2435
2543
  this.startDisabledTimeline();
2436
- });
2437
- }
2544
+ }
2545
+ });
2438
2546
  }
2439
2547
  _clearVariantSelection() {
2440
2548
  forEach(this.variants, function (variant) {
@@ -2781,6 +2889,13 @@ class WidgetPoll extends WidgetBase {
2781
2889
  /** @deprecated */
2782
2890
  initWidget: function (element, localData) {
2783
2891
  WidgetPoll.initWidgets((element, options) => new WidgetPoll(element, options), [element], localData);
2892
+ WidgetPoll.getInstance(element)?.onStart();
2893
+ },
2894
+ onStart: function (element) {
2895
+ WidgetPoll.getInstance(element)?.onStart();
2896
+ },
2897
+ onStop: function (element) {
2898
+ WidgetPoll.getInstance(element)?.onStop();
2784
2899
  },
2785
2900
  /**
2786
2901
  * click
@@ -2855,14 +2970,13 @@ class WidgetPollLayers extends WidgetBase {
2855
2970
  * @param localData
2856
2971
  */
2857
2972
  onRefreshUserData(localData) {
2858
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
2859
- this.localData = extend({}, this.savedData ?? {}, localData);
2973
+ super.onRefreshUserData(localData);
2860
2974
  this.selectedVariant = undefined;
2861
2975
  if (this.slidePollIsDone()) {
2862
2976
  this._selectVariant(this.localData["_pl_g_" + this.elementId + "_sa"]);
2863
2977
  }
2864
2978
  else {
2865
- this._showLayout(this.layers, 0);
2979
+ this._showLayer(this.layers, 0);
2866
2980
  }
2867
2981
  this.firstOpenTime = new Date().getTime();
2868
2982
  }
@@ -2908,10 +3022,12 @@ class WidgetPollLayers extends WidgetBase {
2908
3022
  else if (index === 1) {
2909
3023
  layerIndex = 2;
2910
3024
  }
2911
- this._showLayout(this.layers, layerIndex, userAction);
2912
- if (this.disableTimer) {
2913
- this.startDisabledTimeline();
2914
- }
3025
+ this._showLayer(this.layers, layerIndex, userAction);
3026
+ this.startReadyPromise.then(() => {
3027
+ if (this.disableTimer) {
3028
+ this.startDisabledTimeline();
3029
+ }
3030
+ });
2915
3031
  }
2916
3032
  selectVariant(variant) {
2917
3033
  if (this.selectedVariant !== undefined) {
@@ -2968,6 +3084,13 @@ class WidgetPollLayers extends WidgetBase {
2968
3084
  localData = undefined;
2969
3085
  }
2970
3086
  WidgetPollLayers.initWidgets((element, options) => new WidgetPollLayers(element, { ...options, layers }), [element], localData);
3087
+ WidgetPollLayers.getInstance(element)?.onStart();
3088
+ },
3089
+ onStart: function (element) {
3090
+ WidgetPollLayers.getInstance(element)?.onStart();
3091
+ },
3092
+ onStop: function (element) {
3093
+ WidgetPollLayers.getInstance(element)?.onStop();
2971
3094
  },
2972
3095
  /**
2973
3096
  * click on poll variant
@@ -3002,6 +3125,7 @@ class WidgetQuest extends WidgetBase {
3002
3125
  isWidget;
3003
3126
  slideCount;
3004
3127
  nonFinalSlide;
3128
+ slideDisabledNavigation;
3005
3129
  finalSlide;
3006
3130
  constructor(element, options) {
3007
3131
  const isWidget = !hasClass(element, "narrative-slide");
@@ -3014,6 +3138,7 @@ class WidgetQuest extends WidgetBase {
3014
3138
  this.finalSlide = !this.isWidget && !this.nonFinalSlide;
3015
3139
  this.label = this.element.querySelector(".label-view .label");
3016
3140
  this.variants = slice.call(this.element.querySelectorAll(".variants-box .variant-view"));
3141
+ this.slideDisabledNavigation = Boolean(getTagDataAsNumber(this.slide, "disableNavigation") ?? 0);
3017
3142
  this.selectedAnswer = undefined;
3018
3143
  }
3019
3144
  /**
@@ -3021,8 +3146,7 @@ class WidgetQuest extends WidgetBase {
3021
3146
  * @param localData
3022
3147
  */
3023
3148
  onRefreshUserData(localData) {
3024
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
3025
- this.localData = extend({}, this.savedData ?? {}, localData);
3149
+ super.onRefreshUserData(localData);
3026
3150
  }
3027
3151
  setCardSessionValue(name, value) {
3028
3152
  this.sdkApi.setCardSessionValue(this.element, name, value);
@@ -3159,6 +3283,10 @@ class WidgetQuest extends WidgetBase {
3159
3283
  const directionForward = event.direction === "forward";
3160
3284
  event.direction === "backward";
3161
3285
  if (this.isWidget) {
3286
+ // like in web-sdk - simple block tap navigation at all
3287
+ if (this.slideDisabledNavigation) {
3288
+ return;
3289
+ }
3162
3290
  if (directionForward) {
3163
3291
  return;
3164
3292
  }
@@ -3182,6 +3310,10 @@ class WidgetQuest extends WidgetBase {
3182
3310
  }
3183
3311
  }
3184
3312
  else {
3313
+ // like in web-sdk - simple block tap navigation at all
3314
+ if (this.slideDisabledNavigation) {
3315
+ return;
3316
+ }
3185
3317
  // slides without quest form
3186
3318
  // simple slide case
3187
3319
  if (this.nonFinalSlide || event.slideIndex < this.firstSlideWithQuestIndex()) {
@@ -3275,8 +3407,15 @@ class WidgetQuest extends WidgetBase {
3275
3407
  resolve(true);
3276
3408
  }
3277
3409
  });
3410
+ WidgetQuest.getInstance(element)?.onStart();
3278
3411
  });
3279
3412
  },
3413
+ onStart: function (element) {
3414
+ WidgetQuest.getInstance(element)?.onStart();
3415
+ },
3416
+ onStop: function (element) {
3417
+ WidgetQuest.getInstance(element)?.onStop();
3418
+ },
3280
3419
  select: function (element) {
3281
3420
  const widgetElement = element.closest(`.${WidgetQuest.widgetClassName}`);
3282
3421
  if (widgetElement) {
@@ -3327,8 +3466,7 @@ class WidgetQuiz extends WidgetBase {
3327
3466
  * @param localData
3328
3467
  */
3329
3468
  onRefreshUserData(localData) {
3330
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
3331
- this.localData = extend({}, this.savedData ?? {}, localData);
3469
+ super.onRefreshUserData(localData);
3332
3470
  this.selectedAnswer = undefined;
3333
3471
  if (this.localData) {
3334
3472
  if (this.localData["_q_g_" + this.elementId + "_sa"] !== undefined) {
@@ -3371,9 +3509,11 @@ class WidgetQuiz extends WidgetBase {
3371
3509
  // })
3372
3510
  // })
3373
3511
  // }
3374
- if (this.disableTimer) {
3375
- this.startDisabledTimeline();
3376
- }
3512
+ this.startReadyPromise.then(() => {
3513
+ if (this.disableTimer) {
3514
+ this.startDisabledTimeline();
3515
+ }
3516
+ });
3377
3517
  }
3378
3518
  _clearAnswerSelection() {
3379
3519
  forEach(this.answers, function (answer) {
@@ -3472,6 +3612,13 @@ class WidgetQuiz extends WidgetBase {
3472
3612
  /** @deprecated */
3473
3613
  initWidget: function (element, localData) {
3474
3614
  WidgetQuiz.initWidgets((element, options) => new WidgetQuiz(element, options), [element], localData);
3615
+ WidgetQuiz.getInstance(element)?.onStart();
3616
+ },
3617
+ onStart: function (element) {
3618
+ WidgetQuiz.getInstance(element)?.onStart();
3619
+ },
3620
+ onStop: function (element) {
3621
+ WidgetQuiz.getInstance(element)?.onStop();
3475
3622
  },
3476
3623
  /**
3477
3624
  * click on quiz answer
@@ -3525,8 +3672,7 @@ class WidgetQuizGrouped extends WidgetBase {
3525
3672
  * @param localData
3526
3673
  */
3527
3674
  onRefreshUserData(localData) {
3528
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
3529
- this.localData = extend({}, this.savedData ?? {}, localData);
3675
+ super.onRefreshUserData(localData);
3530
3676
  this.selectedAnswer = undefined;
3531
3677
  if (this.localData) {
3532
3678
  if (this.localData["_q_gg_" + this.elementId + "_sa"] !== undefined) {
@@ -3556,9 +3702,11 @@ class WidgetQuizGrouped extends WidgetBase {
3556
3702
  this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
3557
3703
  }
3558
3704
  });
3559
- if (this.disableTimer) {
3560
- this.startDisabledTimeline();
3561
- }
3705
+ this.startReadyPromise.then(() => {
3706
+ if (this.disableTimer) {
3707
+ this.startDisabledTimeline();
3708
+ }
3709
+ });
3562
3710
  }
3563
3711
  _clearAnswerSelection() {
3564
3712
  forEach(this.answers, function (answer) {
@@ -3674,6 +3822,13 @@ class WidgetQuizGrouped extends WidgetBase {
3674
3822
  /** @deprecated */
3675
3823
  initWidget: function (element, localData) {
3676
3824
  WidgetQuizGrouped.initWidgets((element, options) => new WidgetQuizGrouped(element, options), [element], localData);
3825
+ WidgetQuizGrouped.getInstance(element)?.onStart();
3826
+ },
3827
+ onStart: function (element) {
3828
+ WidgetQuizGrouped.getInstance(element)?.onStart();
3829
+ },
3830
+ onStop: function (element) {
3831
+ WidgetQuizGrouped.getInstance(element)?.onStop();
3677
3832
  },
3678
3833
  /**
3679
3834
  * click on quiz answer
@@ -3919,15 +4074,16 @@ class WidgetRangeSlider extends WidgetBase {
3919
4074
  * @param localData
3920
4075
  */
3921
4076
  onRefreshUserData(localData) {
3922
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
3923
- this.localData = extend({}, this.savedData ?? {}, localData);
4077
+ super.onRefreshUserData(localData);
3924
4078
  if (this.localData["_rs_g_" + this.elementId + "_v"] !== undefined) {
3925
4079
  this.elementSlider.value = String(tryParseFloat(this.localData["_rs_g_" + this.elementId + "_v"], 0));
3926
4080
  this.element.classList.add("done");
3927
4081
  this.displayAverageAnswer();
3928
- if (this.disableTimer) {
3929
- this.startDisabledTimeline();
3930
- }
4082
+ this.startReadyPromise.then(() => {
4083
+ if (this.disableTimer) {
4084
+ this.startDisabledTimeline();
4085
+ }
4086
+ });
3931
4087
  }
3932
4088
  else {
3933
4089
  this.elementSlider.value = String(this.startValue);
@@ -3936,6 +4092,10 @@ class WidgetRangeSlider extends WidgetBase {
3936
4092
  }
3937
4093
  this.init();
3938
4094
  }
4095
+ onStop() {
4096
+ super.onStop();
4097
+ this.destroy();
4098
+ }
3939
4099
  _statEventInputSave(val) {
3940
4100
  try {
3941
4101
  const labelText = this.label?.textContent ?? "";
@@ -4112,10 +4272,10 @@ class WidgetRangeSlider extends WidgetBase {
4112
4272
  if (!this.maxHandlePos) {
4113
4273
  this.update(true, false);
4114
4274
  }
4115
- document.addEventListener("touchmove", this.handleMove);
4116
- document.addEventListener("touchend", this.handleEnd);
4117
- document.addEventListener("mousemove", this.handleMove);
4118
- document.addEventListener("mouseup", this.handleEnd);
4275
+ this.env.document.addEventListener("touchmove", this.handleMove);
4276
+ this.env.document.addEventListener("touchend", this.handleEnd);
4277
+ this.env.document.addEventListener("mousemove", this.handleMove);
4278
+ this.env.document.addEventListener("mouseup", this.handleEnd);
4119
4279
  // add active class because Firefox is ignoring
4120
4280
  // the handle:active pseudo selector because of `e.preventDefault();`
4121
4281
  this.range.classList.add(this.options.activeClass);
@@ -4140,10 +4300,10 @@ class WidgetRangeSlider extends WidgetBase {
4140
4300
  this.isClickCapturedBySlider = false;
4141
4301
  });
4142
4302
  // e.preventDefault();
4143
- document.removeEventListener("touchmove", this.handleMove);
4144
- document.removeEventListener("touchend", this.handleEnd);
4145
- document.removeEventListener("mousemove", this.handleMove);
4146
- document.removeEventListener("mouseup", this.handleEnd);
4303
+ this.env.document.removeEventListener("touchmove", this.handleMove);
4304
+ this.env.document.removeEventListener("touchend", this.handleEnd);
4305
+ this.env.document.removeEventListener("mousemove", this.handleMove);
4306
+ this.env.document.removeEventListener("mouseup", this.handleEnd);
4147
4307
  this.range.classList.remove(this.options.activeClass);
4148
4308
  this.element.classList.add("input-done");
4149
4309
  if (!this.hasSubmitButton) {
@@ -4287,11 +4447,18 @@ class WidgetRangeSlider extends WidgetBase {
4287
4447
  onRefreshUserData: WidgetRangeSlider.onRefreshUserData,
4288
4448
  init: function (element, localData) {
4289
4449
  WidgetRangeSlider.initWidget(element, localData, (element, options) => new WidgetRangeSlider(element, options));
4450
+ WidgetRangeSlider.getInstance(element)?.onStart();
4290
4451
  },
4291
4452
  /** @deprecated */
4292
4453
  initWidget: function (element, localData) {
4293
4454
  WidgetRangeSlider.initWidgets((element, options) => new WidgetRangeSlider(element, options), [element], localData);
4294
4455
  },
4456
+ onStart: function (element) {
4457
+ WidgetRangeSlider.getInstance(element)?.onStart();
4458
+ },
4459
+ onStop: function (element) {
4460
+ WidgetRangeSlider.getInstance(element)?.onStop();
4461
+ },
4295
4462
  click: function (element) {
4296
4463
  const widgetElement = element.closest(`.${WidgetRangeSlider.widgetClassName}`);
4297
4464
  if (widgetElement) {
@@ -4352,8 +4519,7 @@ class WidgetRate extends WidgetBase {
4352
4519
  * @param localData
4353
4520
  */
4354
4521
  onRefreshUserData(localData) {
4355
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
4356
- this.localData = extend({}, this.savedData ?? {}, localData);
4522
+ super.onRefreshUserData(localData);
4357
4523
  this.selectedStar = undefined;
4358
4524
  if (this.localData) {
4359
4525
  if (this.localData["_r_g_" + this.elementId + "_ss"] !== undefined) {
@@ -4411,9 +4577,11 @@ class WidgetRate extends WidgetBase {
4411
4577
  this.selectedStar = value;
4412
4578
  this.localData["_r_g_" + this.elementId + "_ss"] = value;
4413
4579
  this.element.classList.add("done");
4414
- if (this.disableTimer && runTimer) {
4415
- this.startDisabledTimeline();
4416
- }
4580
+ this.startReadyPromise.then(() => {
4581
+ if (this.disableTimer && runTimer) {
4582
+ this.startDisabledTimeline();
4583
+ }
4584
+ });
4417
4585
  }
4418
4586
  _clearSelectedStar() {
4419
4587
  forEach(this.stars, function (element) {
@@ -4546,7 +4714,15 @@ class WidgetRate extends WidgetBase {
4546
4714
  },
4547
4715
  /** @deprecated */
4548
4716
  initWidget: function (nodeList, localData) {
4549
- WidgetRate.initWidgets((element, options) => new WidgetRate(element, options), slice.call(nodeList), localData);
4717
+ const elements = slice.call(nodeList);
4718
+ WidgetRate.initWidgets((element, options) => new WidgetRate(element, options), elements, localData);
4719
+ elements.forEach(element => WidgetRate.getInstance(element)?.onStart());
4720
+ },
4721
+ onStart: function (element) {
4722
+ WidgetRate.getInstance(element)?.onStart();
4723
+ },
4724
+ onStop: function (element) {
4725
+ WidgetRate.getInstance(element)?.onStop();
4550
4726
  },
4551
4727
  select: function (element) {
4552
4728
  const widgetElement = element.closest(`.${WidgetRate.widgetClassName}`);
@@ -4598,19 +4774,20 @@ class WidgetShare extends WidgetBase {
4598
4774
  * @param localData
4599
4775
  */
4600
4776
  onRefreshUserData(localData) {
4601
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
4602
- this.localData = extend({}, this.savedData ?? {}, localData);
4777
+ super.onRefreshUserData(localData);
4603
4778
  if (this.withLayer) {
4604
4779
  if (this.isDone()) {
4605
- this._showLayout(this.layers, 1);
4780
+ this._showLayer(this.layers, 1);
4606
4781
  }
4607
4782
  else {
4608
- this._showLayout(this.layers, 0);
4783
+ this._showLayer(this.layers, 0);
4609
4784
  }
4610
4785
  }
4611
- if (this.isDone() && this.disableTimer) {
4612
- this.startDisabledTimeline();
4613
- }
4786
+ this.startReadyPromise.then(() => {
4787
+ if (this.isDone() && this.disableTimer) {
4788
+ this.startDisabledTimeline();
4789
+ }
4790
+ });
4614
4791
  this.btnDisabled = false;
4615
4792
  }
4616
4793
  _statEventShare(result, via) {
@@ -4665,7 +4842,7 @@ class WidgetShare extends WidgetBase {
4665
4842
  }
4666
4843
  this._statEventShare(isSuccess, null);
4667
4844
  if (isSuccess && this.withLayer) {
4668
- this._showLayout(this.layers, 1, true);
4845
+ this._showLayer(this.layers, 1, true);
4669
4846
  }
4670
4847
  if (this.disableTimer) {
4671
4848
  this.startDisabledTimeline();
@@ -4681,7 +4858,10 @@ class WidgetShare extends WidgetBase {
4681
4858
  refreshUserData: WidgetShare.refreshUserData,
4682
4859
  onRefreshUserData: WidgetShare.onRefreshUserData,
4683
4860
  init: function (element, layers, localData) {
4684
- WidgetShare.initWidget(element, localData, (element, options) => new WidgetShare(element, { ...options, layers }));
4861
+ WidgetShare.initWidget(element, localData, (element, options) => new WidgetShare(element, {
4862
+ ...options,
4863
+ layers,
4864
+ }));
4685
4865
  },
4686
4866
  /** @deprecated
4687
4867
  * signature variants
@@ -4695,7 +4875,15 @@ class WidgetShare extends WidgetBase {
4695
4875
  layers = localData;
4696
4876
  localData = undefined;
4697
4877
  }
4698
- WidgetShare.initWidgets((element, options) => new WidgetShare(element, { ...options, layers }), slice.call(nodeList), localData);
4878
+ const elements = slice.call(nodeList);
4879
+ WidgetShare.initWidgets((element, options) => new WidgetShare(element, { ...options, layers }), elements, localData);
4880
+ elements.forEach(element => WidgetShare.getInstance(element)?.onStart());
4881
+ },
4882
+ onStart: function (element) {
4883
+ WidgetShare.getInstance(element)?.onStart();
4884
+ },
4885
+ onStop: function (element) {
4886
+ WidgetShare.getInstance(element)?.onStop();
4699
4887
  },
4700
4888
  click: function (element) {
4701
4889
  const widgetElement = element.closest(`.${WidgetShare.widgetClassName}`);
@@ -4775,8 +4963,7 @@ class WidgetTest extends WidgetBase {
4775
4963
  * @param localData
4776
4964
  */
4777
4965
  onRefreshUserData(localData) {
4778
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
4779
- this.localData = extend({}, this.savedData ?? {}, localData);
4966
+ super.onRefreshUserData(localData);
4780
4967
  this.selectedAnswer = undefined;
4781
4968
  if (this.localData) {
4782
4969
  if (this.localData["_t_g_" + this.elementId + "_sa"] !== undefined) {
@@ -4800,7 +4987,9 @@ class WidgetTest extends WidgetBase {
4800
4987
  this.timeLeft = this.timeLeftDefault;
4801
4988
  this.animationFrameId = null;
4802
4989
  this.startTimerAt = new Date().getTime();
4803
- this.tick();
4990
+ this.startReadyPromise.then(() => {
4991
+ this.tick();
4992
+ });
4804
4993
  // set answer - unanswered (for close and run again)
4805
4994
  this.localData["_t_g_" + this.elementId + "_sa"] = -1;
4806
4995
  this.setLocalData(this.localData, true);
@@ -4820,6 +5009,15 @@ class WidgetTest extends WidgetBase {
4820
5009
  }
4821
5010
  }
4822
5011
  }
5012
+ onStart() {
5013
+ super.onStart();
5014
+ }
5015
+ onStop() {
5016
+ super.onStop();
5017
+ if (this.slideTestWithTimer()) {
5018
+ this.cancelTick();
5019
+ }
5020
+ }
4823
5021
  _statEventVoteAnswer(answerScore) {
4824
5022
  try {
4825
5023
  if (this.selectedAnswer != null) {
@@ -4867,9 +5065,11 @@ class WidgetTest extends WidgetBase {
4867
5065
  this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
4868
5066
  }
4869
5067
  });
4870
- if (this.disableTimer) {
4871
- this.startDisabledTimeline();
4872
- }
5068
+ this.startReadyPromise.then(() => {
5069
+ if (this.disableTimer) {
5070
+ this.startDisabledTimeline();
5071
+ }
5072
+ });
4873
5073
  }
4874
5074
  selectAnswer(answer) {
4875
5075
  if (this.selectedAnswer !== undefined) {
@@ -4948,6 +5148,13 @@ class WidgetTest extends WidgetBase {
4948
5148
  /** @deprecated */
4949
5149
  initWidget: function (element, localData) {
4950
5150
  WidgetTest.initWidgets((element, options) => new WidgetTest(element, options), [element], localData);
5151
+ WidgetTest.getInstance(element)?.onStart();
5152
+ },
5153
+ onStart: function (element) {
5154
+ WidgetTest.getInstance(element)?.onStart();
5155
+ },
5156
+ onStop: function (element) {
5157
+ WidgetTest.getInstance(element)?.onStop();
4951
5158
  },
4952
5159
  /**
4953
5160
  * click on quiz answer
@@ -5057,8 +5264,7 @@ class WidgetVote extends WidgetBase {
5057
5264
  * @param localData
5058
5265
  */
5059
5266
  onRefreshUserData(localData) {
5060
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
5061
- this.localData = extend({}, this.savedData ?? {}, localData);
5267
+ super.onRefreshUserData(localData);
5062
5268
  this.selectedVariant = undefined;
5063
5269
  if (this.localData) {
5064
5270
  if (this.localData["_v_g_" + this.elementId + "_sa"] != null) {
@@ -5188,9 +5394,11 @@ class WidgetVote extends WidgetBase {
5188
5394
  this._removeInputDone();
5189
5395
  this._hideSubmitBtn();
5190
5396
  }
5191
- if (this.disableTimer) {
5192
- this.startDisabledTimeline();
5193
- }
5397
+ this.startReadyPromise.then(() => {
5398
+ if (this.disableTimer) {
5399
+ this.startDisabledTimeline();
5400
+ }
5401
+ });
5194
5402
  }
5195
5403
  _showSubmitBtn() {
5196
5404
  this.env.requestAnimationFrame(() => {
@@ -5421,6 +5629,13 @@ class WidgetVote extends WidgetBase {
5421
5629
  WidgetVote.initWidgets((element, options) => new WidgetVote(element, options), [element], localData).then(localData => {
5422
5630
  WidgetVote.api.fallbackInitOnMultiSlide(element, localData);
5423
5631
  });
5632
+ WidgetVote.getInstance(element)?.onStart();
5633
+ },
5634
+ onStart: function (element) {
5635
+ WidgetVote.getInstance(element)?.onStart();
5636
+ },
5637
+ onStop: function (element) {
5638
+ WidgetVote.getInstance(element)?.onStop();
5424
5639
  },
5425
5640
  select: function (element) {
5426
5641
  const widgetElement = element.closest(`.${WidgetVote.widgetClassName}`);
@@ -14849,17 +15064,22 @@ class WidgetBarcode extends WidgetBase {
14849
15064
  * @param localData
14850
15065
  */
14851
15066
  onRefreshUserData(localData) {
14852
- this.savedData = this.sdkApi.getCardServerData(this.cardId);
14853
- this.localData = extend({}, this.savedData ?? {}, localData);
15067
+ super.onRefreshUserData(localData);
14854
15068
  this.state = null;
14855
15069
  if (this.isPromotionalCode) {
14856
- this.fetchPromoCode();
15070
+ this.initPromotionalCodeFromLocalData();
14857
15071
  }
14858
15072
  else {
14859
15073
  this.renderCodeView();
14860
15074
  this.renderCaptionView();
14861
15075
  }
14862
15076
  }
15077
+ onStart() {
15078
+ super.onStart();
15079
+ if (this.isPromotionalCode) {
15080
+ this.fetchPromoCode();
15081
+ }
15082
+ }
14863
15083
  isTransparentElement() {
14864
15084
  if (this.element) {
14865
15085
  try {
@@ -14941,17 +15161,23 @@ class WidgetBarcode extends WidgetBase {
14941
15161
  this.captionView.textContent = text;
14942
15162
  }
14943
15163
  }
14944
- fetchPromoCode() {
14945
- this.state = 0;
14946
- if (this.localData["_bc_g_" + this.elementId + "_pc"] !== undefined) {
15164
+ getPromotionalCodeFromLocalData() {
15165
+ return this.localData["_bc_g_" + this.elementId + "_pc"];
15166
+ }
15167
+ initPromotionalCodeFromLocalData() {
15168
+ if (this.getPromotionalCodeFromLocalData() !== undefined) {
14947
15169
  this.state = 1;
14948
- this.clipboardTarget = this.localData["_bc_g_" + this.elementId + "_pc"];
15170
+ this.clipboardTarget = this.getPromotionalCodeFromLocalData();
14949
15171
  if (this.clipboardTarget != null) {
14950
15172
  this.renderCaptionView();
14951
15173
  this.renderCodeView();
14952
15174
  }
14953
15175
  removeClass(this.element, "loader");
14954
15176
  }
15177
+ }
15178
+ fetchPromoCode() {
15179
+ this.state = 0;
15180
+ this.initPromotionalCodeFromLocalData();
14955
15181
  if (this.state === 0) {
14956
15182
  if (!this.isTransparentElement()) {
14957
15183
  // for transparent element
@@ -15037,12 +15263,14 @@ class WidgetBarcode extends WidgetBase {
15037
15263
  }
15038
15264
  _select() {
15039
15265
  this.element.classList.add("done");
15040
- if (this.disableTimer) {
15041
- // флаг - что таймер уже стартанул (в layout или добавить объект sharedMemory)
15042
- // смотрим что прозрачный текст - тогда и лоадер прозрачный
15043
- // _log("_showNarrativeNextSlide: " + getSlideDuration(this.narrativeId, this.slideIndex), true);
15044
- this.startDisabledTimeline();
15045
- }
15266
+ this.startReadyPromise.then(() => {
15267
+ if (this.disableTimer) {
15268
+ // флаг - что таймер уже стартанул layout или добавить объект sharedMemory)
15269
+ // смотрим что прозрачный текст - тогда и лоадер прозрачный
15270
+ // _log("_showNarrativeNextSlide: " + getSlideDuration(this.narrativeId, this.slideIndex), true);
15271
+ this.startDisabledTimeline();
15272
+ }
15273
+ });
15046
15274
  if (this.copiedText) {
15047
15275
  this.sdkApi.showToast(this.copiedText);
15048
15276
  }
@@ -15073,7 +15301,15 @@ class WidgetBarcode extends WidgetBase {
15073
15301
  },
15074
15302
  /** @deprecated */
15075
15303
  initWidget: function (nodeList, localData) {
15076
- WidgetBarcode.initWidgets((element, options) => new WidgetBarcode(element, options), slice.call(nodeList), localData);
15304
+ const elements = slice.call(nodeList);
15305
+ WidgetBarcode.initWidgets((element, options) => new WidgetBarcode(element, options), elements, localData);
15306
+ elements.forEach(element => WidgetBarcode.getInstance(element)?.onStart());
15307
+ },
15308
+ onStart: function (element) {
15309
+ WidgetBarcode.getInstance(element)?.onStart();
15310
+ },
15311
+ onStop: function (element) {
15312
+ WidgetBarcode.getInstance(element)?.onStop();
15077
15313
  },
15078
15314
  click: function (element) {
15079
15315
  const widgetElement = element.closest(`.${WidgetBarcode.widgetClassName}`);
@@ -15097,6 +15333,1045 @@ class WidgetBarcode extends WidgetBase {
15097
15333
  static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
15098
15334
  }
15099
15335
 
15336
+ class Formatter {
15337
+ intlSupport = false;
15338
+ defaultTimeFormat = "medium";
15339
+ defaultDatetimeFormat = "medium";
15340
+ defaultDateFormat = "medium";
15341
+ decimalSeparator = ".";
15342
+ thousandSeparator = "&thinsp;";
15343
+ spaceSeparator = "&thinsp;";
15344
+ static Second = 1000;
15345
+ static Minute = 60 * Formatter.Second;
15346
+ static Hour = 60 * Formatter.Minute;
15347
+ static Day = 24 * Formatter.Hour;
15348
+ datetimeFormatOptions = {
15349
+ short: {
15350
+ year: "numeric",
15351
+ month: "2-digit",
15352
+ day: "2-digit",
15353
+ hour: "2-digit",
15354
+ minute: "2-digit",
15355
+ },
15356
+ medium: {
15357
+ year: "numeric",
15358
+ month: "2-digit",
15359
+ day: "2-digit",
15360
+ hour: "2-digit",
15361
+ minute: "2-digit",
15362
+ second: "2-digit",
15363
+ },
15364
+ long: {
15365
+ year: "numeric",
15366
+ month: "long",
15367
+ day: "2-digit",
15368
+ hour: "2-digit",
15369
+ minute: "2-digit",
15370
+ second: "2-digit",
15371
+ timeZoneName: "short",
15372
+ },
15373
+ full: {
15374
+ weekday: "long",
15375
+ year: "numeric",
15376
+ month: "long",
15377
+ day: "2-digit",
15378
+ hour: "2-digit",
15379
+ minute: "2-digit",
15380
+ second: "2-digit",
15381
+ timeZoneName: "long",
15382
+ },
15383
+ };
15384
+ dateFormatOptions = {
15385
+ short: {
15386
+ year: "2-digit",
15387
+ month: "2-digit",
15388
+ day: "2-digit",
15389
+ },
15390
+ medium: {
15391
+ year: "numeric",
15392
+ month: "2-digit",
15393
+ day: "2-digit",
15394
+ },
15395
+ long: {
15396
+ year: "numeric",
15397
+ month: "long",
15398
+ day: "2-digit",
15399
+ },
15400
+ full: {
15401
+ weekday: "long",
15402
+ year: "numeric",
15403
+ month: "long",
15404
+ day: "2-digit",
15405
+ },
15406
+ };
15407
+ timeFormatOptions = {
15408
+ short: {
15409
+ hour: "2-digit",
15410
+ minute: "2-digit",
15411
+ },
15412
+ medium: {
15413
+ hour: "2-digit",
15414
+ minute: "2-digit",
15415
+ second: "2-digit",
15416
+ },
15417
+ long: {
15418
+ hour: "2-digit",
15419
+ minute: "2-digit",
15420
+ second: "2-digit",
15421
+ timeZoneName: "short",
15422
+ },
15423
+ full: {
15424
+ hour: "2-digit",
15425
+ minute: "2-digit",
15426
+ second: "2-digit",
15427
+ timeZoneName: "long",
15428
+ },
15429
+ };
15430
+ context;
15431
+ constructor(context) {
15432
+ this.intlSupport = typeof Intl === "object" && Intl !== null;
15433
+ this.context = context;
15434
+ }
15435
+ asDate(value, format = undefined, options = {}) {
15436
+ if (!format) {
15437
+ format = this.defaultDateFormat;
15438
+ }
15439
+ return this.formatDateTimeValue(value, format, "date", options);
15440
+ }
15441
+ asTime(value, format = undefined, options = {}) {
15442
+ if (!format) {
15443
+ format = this.defaultTimeFormat;
15444
+ }
15445
+ return this.formatDateTimeValue(value, format, "time", options);
15446
+ }
15447
+ asDatetime(value, format = undefined, options = {}) {
15448
+ if (!format) {
15449
+ format = this.defaultTimeFormat;
15450
+ }
15451
+ return this.formatDateTimeValue(value, format, "datetime", options);
15452
+ }
15453
+ formatDateTimeValue(value, format = undefined, type = undefined, options = {}) {
15454
+ const normalizedValue = Formatter.normalizeDatetimeValue(value);
15455
+ if (normalizedValue === null) {
15456
+ return "";
15457
+ }
15458
+ if (this.intlSupport) {
15459
+ let formatterOptions = {};
15460
+ if (type === "date") {
15461
+ if (typeof format === "undefined") {
15462
+ format = this.defaultDateFormat;
15463
+ }
15464
+ if (typeof format === "object") {
15465
+ formatterOptions = format;
15466
+ }
15467
+ else {
15468
+ if (format in this.dateFormatOptions) {
15469
+ formatterOptions = this.dateFormatOptions[format];
15470
+ }
15471
+ else {
15472
+ return this.momentFallback(normalizedValue, format, options);
15473
+ }
15474
+ }
15475
+ }
15476
+ else if (type === "time") {
15477
+ if (typeof format === "undefined") {
15478
+ format = this.defaultTimeFormat;
15479
+ }
15480
+ if (typeof format === "object") {
15481
+ formatterOptions = format;
15482
+ }
15483
+ else {
15484
+ if (format in this.timeFormatOptions) {
15485
+ formatterOptions = this.timeFormatOptions[format];
15486
+ }
15487
+ else {
15488
+ return this.momentFallback(normalizedValue, format, options);
15489
+ }
15490
+ }
15491
+ }
15492
+ else if (type === "datetime") {
15493
+ if (typeof format === "undefined") {
15494
+ format = this.defaultDatetimeFormat;
15495
+ }
15496
+ if (typeof format === "object") {
15497
+ formatterOptions = format;
15498
+ }
15499
+ else {
15500
+ if (format in this.datetimeFormatOptions) {
15501
+ formatterOptions = this.datetimeFormatOptions[format];
15502
+ }
15503
+ else {
15504
+ return this.momentFallback(normalizedValue, format, options);
15505
+ }
15506
+ }
15507
+ }
15508
+ if (options.timezone) {
15509
+ formatterOptions.timeZone = options.timezone;
15510
+ }
15511
+ Intl.DateTimeFormat(this.locale, formatterOptions).format(normalizedValue);
15512
+ return Intl.DateTimeFormat(this.locale, formatterOptions).format(normalizedValue);
15513
+ }
15514
+ return "";
15515
+ }
15516
+ momentFallback(value, format, options = {}) {
15517
+ return value.toLocaleString(this.locale);
15518
+ // return this.context.$moment(value).format(format);
15519
+ }
15520
+ asInteger(value) {
15521
+ if (value === undefined || value === null) {
15522
+ return this.nullDisplay;
15523
+ }
15524
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15525
+ if (this.intlSupport) {
15526
+ return Intl.NumberFormat(this.locale, {
15527
+ maximumFractionDigits: 0,
15528
+ useGrouping: true,
15529
+ }).format(normalizedValue);
15530
+ }
15531
+ return Formatter.numberFormat(normalizedValue, 0, this.decimalSeparator, this.thousandSeparator);
15532
+ }
15533
+ asDecimal(value, decimals = 2) {
15534
+ if (value == null) {
15535
+ return this.nullDisplay;
15536
+ }
15537
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15538
+ if (this.intlSupport) {
15539
+ return Intl.NumberFormat(this.locale, {
15540
+ maximumFractionDigits: decimals,
15541
+ minimumFractionDigits: decimals,
15542
+ useGrouping: true,
15543
+ }).format(normalizedValue);
15544
+ }
15545
+ return Formatter.numberFormat(normalizedValue, decimals, this.decimalSeparator, this.thousandSeparator);
15546
+ }
15547
+ asDecimalMax(value, decimals = 2) {
15548
+ if (value === undefined || value === null) {
15549
+ return this.nullDisplay;
15550
+ }
15551
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15552
+ if (this.intlSupport) {
15553
+ return Intl.NumberFormat(this.locale, {
15554
+ maximumFractionDigits: decimals,
15555
+ minimumFractionDigits: 0,
15556
+ useGrouping: true,
15557
+ }).format(normalizedValue);
15558
+ }
15559
+ return Formatter.numberFormat(normalizedValue, decimals, this.decimalSeparator, this.thousandSeparator);
15560
+ }
15561
+ asPercent(value, decimals = 0) {
15562
+ if (value === undefined || value === null) {
15563
+ return this.nullDisplay;
15564
+ }
15565
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15566
+ if (this.intlSupport) {
15567
+ return Intl.NumberFormat(this.locale, {
15568
+ style: "percent",
15569
+ maximumFractionDigits: decimals,
15570
+ minimumFractionDigits: decimals,
15571
+ }).format(normalizedValue);
15572
+ }
15573
+ return Formatter.numberFormat(normalizedValue * 100, decimals, this.decimalSeparator, this.thousandSeparator);
15574
+ }
15575
+ asPercentMax(value, decimals = 0) {
15576
+ if (value === undefined || value === null) {
15577
+ return this.nullDisplay;
15578
+ }
15579
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15580
+ if (this.intlSupport) {
15581
+ return Intl.NumberFormat(this.locale, {
15582
+ style: "percent",
15583
+ maximumFractionDigits: decimals,
15584
+ minimumFractionDigits: 0,
15585
+ }).format(normalizedValue);
15586
+ }
15587
+ return Formatter.numberFormat(normalizedValue * 100, decimals, this.decimalSeparator, this.thousandSeparator);
15588
+ }
15589
+ asRelativeTime(value, referenceTime = undefined) {
15590
+ if (value === undefined || value === null) {
15591
+ return this.nullDisplay;
15592
+ }
15593
+ const normalizedValue = Formatter.normalizeDatetimeValue(value);
15594
+ if (normalizedValue == null) {
15595
+ return this.nullDisplay;
15596
+ }
15597
+ if (referenceTime === undefined || referenceTime === null) {
15598
+ referenceTime = new Date();
15599
+ }
15600
+ else {
15601
+ referenceTime = Formatter.normalizeDatetimeValue(value);
15602
+ }
15603
+ const dt = referenceTime.getTime() - normalizedValue.getTime();
15604
+ const absDt = Math.abs(dt);
15605
+ const invert = dt < 0;
15606
+ if (absDt < Formatter.Second) {
15607
+ return this.context.i18n?.t("format.relativeTime.justNow").toString() ?? "";
15608
+ }
15609
+ const seconds = absDt / 1000;
15610
+ let interval = seconds / 31536000;
15611
+ if (interval > 1) {
15612
+ return this.context.i18n?.tc("format.relativeTime.year" + (invert ? "In" : "Ago"), Math.floor(interval)).toString() ?? "";
15613
+ }
15614
+ interval = seconds / 2592000;
15615
+ if (interval > 1) {
15616
+ return this.context.i18n?.tc("format.relativeTime.month" + (invert ? "In" : "Ago"), Math.floor(interval)).toString() ?? "";
15617
+ }
15618
+ interval = seconds / 86400;
15619
+ if (interval > 1) {
15620
+ return this.context.i18n?.tc("format.relativeTime.day" + (invert ? "In" : "Ago"), Math.floor(interval)).toString() ?? "";
15621
+ }
15622
+ interval = seconds / 3600;
15623
+ if (interval > 1) {
15624
+ return this.context.i18n?.tc("format.relativeTime.hour" + (invert ? "In" : "Ago"), Math.floor(interval)).toString() ?? "";
15625
+ }
15626
+ interval = seconds / 60;
15627
+ if (interval > 1) {
15628
+ return this.context.i18n?.tc("format.relativeTime.minute" + (invert ? "In" : "Ago"), Math.floor(interval)).toString() ?? "";
15629
+ }
15630
+ return this.context.i18n?.tc("format.relativeTime.second" + (invert ? "In" : "Ago"), Math.floor(seconds)).toString() ?? "";
15631
+ }
15632
+ asDuration(value) {
15633
+ if (value === undefined || value === null) {
15634
+ return "00:00";
15635
+ }
15636
+ const normalizedValue = Formatter.normalizeDatetimeValue(value);
15637
+ if (normalizedValue === undefined || normalizedValue === null) {
15638
+ return "00:00";
15639
+ }
15640
+ const hours = Math.floor(value / 3600);
15641
+ const minutes = Math.floor((value / 60) % 60);
15642
+ const seconds = value % 60;
15643
+ if (hours > 0) {
15644
+ return `${hours}:${minutes < 10 ? 0 : ""}${minutes}:${seconds < 10 ? 0 : ""}${seconds}`;
15645
+ }
15646
+ else {
15647
+ return `${minutes < 10 ? 0 : ""}${minutes}:${seconds < 10 ? 0 : ""}${seconds}`;
15648
+ }
15649
+ }
15650
+ asCurrency(value, currency = undefined) {
15651
+ if (value === undefined || value === null) {
15652
+ return this.nullDisplay;
15653
+ }
15654
+ if (currency === undefined || currency === null) {
15655
+ currency = "USD";
15656
+ }
15657
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15658
+ if (normalizedValue == null) {
15659
+ return this.nullDisplay;
15660
+ }
15661
+ let decimals = 2;
15662
+ if (Number.isInteger(normalizedValue)) {
15663
+ decimals = 0;
15664
+ }
15665
+ if (currency === "RUR" || currency === "RUB") {
15666
+ return `${this.asDecimal(normalizedValue, decimals)}${this.spaceSeparator}₽`;
15667
+ }
15668
+ if (this.intlSupport) {
15669
+ try {
15670
+ return Intl.NumberFormat(this.locale, {
15671
+ style: "currency",
15672
+ currency,
15673
+ currencyDisplay: "symbol",
15674
+ maximumFractionDigits: decimals,
15675
+ minimumFractionDigits: decimals,
15676
+ }).format(normalizedValue);
15677
+ }
15678
+ catch (e) {
15679
+ console.error(e);
15680
+ return String(normalizedValue);
15681
+ }
15682
+ }
15683
+ return currency + "&thinsp;" + this.asDecimal(normalizedValue, 2);
15684
+ }
15685
+ asShortSizeCasual(value, dp = 1) {
15686
+ if (value === undefined || value === null) {
15687
+ return this.nullDisplay;
15688
+ }
15689
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15690
+ if (normalizedValue === undefined || normalizedValue === null) {
15691
+ return this.nullDisplay;
15692
+ }
15693
+ const thresh = 1024;
15694
+ if (Math.abs(value) < thresh) {
15695
+ return value + " B";
15696
+ }
15697
+ const units = ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
15698
+ let u = -1;
15699
+ const r = 10 ** dp;
15700
+ do {
15701
+ value /= thresh;
15702
+ ++u;
15703
+ } while (Math.round(Math.abs(value) * r) / r >= thresh && u < units.length - 1);
15704
+ return value.toFixed(dp) + " " + units[u];
15705
+ }
15706
+ asShortSize(value, si = false, dp = 1) {
15707
+ if (value === undefined || value === null) {
15708
+ return this.nullDisplay;
15709
+ }
15710
+ const normalizedValue = Formatter.normalizeNumericValue(value);
15711
+ if (normalizedValue === undefined || normalizedValue === null) {
15712
+ return this.nullDisplay;
15713
+ }
15714
+ const thresh = si ? 1000 : 1024;
15715
+ if (Math.abs(value) < thresh) {
15716
+ return value + " B";
15717
+ }
15718
+ const units = si ? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] : ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
15719
+ let u = -1;
15720
+ const r = 10 ** dp;
15721
+ do {
15722
+ value /= thresh;
15723
+ ++u;
15724
+ } while (Math.round(Math.abs(value) * r) / r >= thresh && u < units.length - 1);
15725
+ return value.toFixed(dp) + " " + units[u];
15726
+ }
15727
+ static numberFormat(value, decimals = 0, decimalSeparator = ".", thousandsSeparator) {
15728
+ const sign = value < 0 ? "-" : "";
15729
+ const sNumber = Math.abs(parseInt((+value || 0).toFixed(decimals))) + "";
15730
+ const len = sNumber.length;
15731
+ const tchunk = len > 3 ? len % 3 : 0;
15732
+ const chFirst = tchunk ? sNumber.substr(0, tchunk) + thousandsSeparator : "";
15733
+ const chRest = sNumber.substr(tchunk).replace(/(\d\d\d)(?=\d)/g, "$1" + thousandsSeparator);
15734
+ const chLast = decimals ? decimalSeparator + (Math.abs(value) - parseFloat(sNumber)).toFixed(decimals).slice(2) : "";
15735
+ return sign + chFirst + chRest + chLast;
15736
+ }
15737
+ get nullDisplay() {
15738
+ return "";
15739
+ // if (this.context && this.context.i18n) {
15740
+ // return this.context.i18n.t("notSet").toString();
15741
+ // }
15742
+ //
15743
+ // return "not set";
15744
+ }
15745
+ static normalizeDatetimeValue(value) {
15746
+ const type = typeof value;
15747
+ if (type === "object" && value instanceof Date) {
15748
+ return value;
15749
+ }
15750
+ else if (type === "number") {
15751
+ return new Date(value);
15752
+ }
15753
+ else if (type === "string") {
15754
+ if (isNaN(value)) {
15755
+ return new Date(parseInt(value));
15756
+ }
15757
+ else {
15758
+ const d = Date.parse(value);
15759
+ if (isNaN(d)) {
15760
+ return null;
15761
+ }
15762
+ return new Date(d);
15763
+ }
15764
+ }
15765
+ return null;
15766
+ }
15767
+ static normalizeNumericValue(value) {
15768
+ const type = typeof value;
15769
+ if ((type === "object" && value === null) || type === "undefined") {
15770
+ return 0;
15771
+ }
15772
+ else if (type === "number") {
15773
+ return value;
15774
+ }
15775
+ return parseFloat(value);
15776
+ }
15777
+ get locale() {
15778
+ return this.context.determineLocale();
15779
+ }
15780
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`{\n determineLocale: () => string;\n i18n: { t: (key: string) => string; tc: (key: string, value: string | number) => string } | undefined;\n }`]; }
15781
+ }
15782
+ const formatter = new Formatter({ determineLocale, i18n: undefined });
15783
+
15784
+ class SwipeGestureDetector {
15785
+ env;
15786
+ isScreenSupportsTouch;
15787
+ canContinueHandleDown;
15788
+ onStart;
15789
+ onUpdate;
15790
+ onEnd;
15791
+ constructor(env, isScreenSupportsTouch, canContinueHandleDown, onStart, onUpdate, onEnd) {
15792
+ this.env = env;
15793
+ this.isScreenSupportsTouch = isScreenSupportsTouch;
15794
+ this.canContinueHandleDown = canContinueHandleDown;
15795
+ this.onStart = onStart;
15796
+ this.onUpdate = onUpdate;
15797
+ this.onEnd = onEnd;
15798
+ // Store context
15799
+ this.handleDown = this.handleDown.bind(this);
15800
+ this.handleMove = this.handleMove.bind(this);
15801
+ this.handleEnd = this.handleEnd.bind(this);
15802
+ this.supportsTouch = false;
15803
+ if (this.isScreenSupportsTouch) {
15804
+ this.env.document.addEventListener("touchstart", this.handleDown, false);
15805
+ }
15806
+ else {
15807
+ this.env.document.addEventListener("mousedown", this.handleDown, false);
15808
+ }
15809
+ }
15810
+ startPageCoordinate = [0, 0];
15811
+ limit = Math.tan(((45 * 1.5) / 180) * Math.PI);
15812
+ pageWidth = window.innerWidth || document.body.clientWidth;
15813
+ threshold = Math.max(1, Math.floor(0.01 * this.pageWidth));
15814
+ supportsTouch = false;
15815
+ handleDown(e) {
15816
+ if (!this.canContinueHandleDown(e)) {
15817
+ return;
15818
+ }
15819
+ this.startPageCoordinate = this.getPageCoordinate(e);
15820
+ if (this.isScreenSupportsTouch) {
15821
+ this.env.document.addEventListener("touchmove", this.handleMove, false);
15822
+ this.env.document.addEventListener("touchend", this.handleEnd, false);
15823
+ }
15824
+ else {
15825
+ this.env.document.addEventListener("mousemove", this.handleMove, false);
15826
+ this.env.document.addEventListener("mouseup", this.handleEnd, false);
15827
+ }
15828
+ this.onStart(e);
15829
+ }
15830
+ handleMove(e) {
15831
+ // console.log("handleMove", { startPageCoordinate: this.startPageCoordinate})
15832
+ // this.currentPageCoordinate = this.getPageCoordinate(e);
15833
+ this.onUpdate(e);
15834
+ }
15835
+ handleEnd(e) {
15836
+ if (this.isScreenSupportsTouch) {
15837
+ this.env.document.removeEventListener("touchmove", this.handleMove);
15838
+ this.env.document.removeEventListener("touchend", this.handleEnd);
15839
+ }
15840
+ else {
15841
+ this.env.document.removeEventListener("mousemove", this.handleMove);
15842
+ this.env.document.removeEventListener("mouseup", this.handleEnd);
15843
+ }
15844
+ const currentPageCoordinate = this.getPageCoordinate(e);
15845
+ let gesture = 0 /* SwipeGesture.undefined */;
15846
+ const x = currentPageCoordinate[0] - this.startPageCoordinate[0];
15847
+ const y = currentPageCoordinate[1] - this.startPageCoordinate[1];
15848
+ // console.log("handleEnd", {currentPageCoordinate, startPageCoordinate: this.startPageCoordinate})
15849
+ let xy = Math.abs(x / y);
15850
+ let yx = Math.abs(y / x);
15851
+ if (Math.abs(x) > this.threshold || Math.abs(y) > this.threshold) {
15852
+ if (yx <= this.limit) {
15853
+ if (x < 0) {
15854
+ gesture = 4 /* SwipeGesture.SwipeLeft */;
15855
+ // @ts-ignore
15856
+ // _log(JSON.stringify({t: "SwipeLeft", yx, x, threshold: this.threshold}), true);
15857
+ }
15858
+ else {
15859
+ // @ts-ignore
15860
+ // _log(JSON.stringify({t: "SwipeRight", yx, x, threshold: this.threshold}), true);
15861
+ gesture = 5 /* SwipeGesture.SwipeRight */;
15862
+ }
15863
+ }
15864
+ if (xy <= this.limit) {
15865
+ if (y < 0) {
15866
+ // @ts-ignore
15867
+ // _log(JSON.stringify({t: "SwipeUp", xy, y, threshold: this.threshold}), true);
15868
+ gesture = 2 /* SwipeGesture.SwipeUp */;
15869
+ }
15870
+ else {
15871
+ // @ts-ignore
15872
+ // _log(JSON.stringify({t: "SwipeDown", xy, y, threshold: this.threshold}), true);
15873
+ gesture = 3 /* SwipeGesture.SwipeDown */;
15874
+ }
15875
+ }
15876
+ }
15877
+ else {
15878
+ // @ts-ignore
15879
+ // _log(JSON.stringify({t: "Tap", x, y, threshold: this.threshold}), true);
15880
+ gesture = 1 /* SwipeGesture.Tap */;
15881
+ }
15882
+ this.onEnd(e, gesture);
15883
+ }
15884
+ destroy() {
15885
+ if (this.isScreenSupportsTouch) {
15886
+ this.env.document.removeEventListener("touchstart", this.handleDown);
15887
+ }
15888
+ else {
15889
+ this.env.document.removeEventListener("mousedown", this.handleDown);
15890
+ }
15891
+ }
15892
+ getPageCoordinate(e) {
15893
+ let x = 0;
15894
+ let y = 0;
15895
+ if (e["clientX"] != null && e["clientY"] != null) {
15896
+ x = e["clientX"];
15897
+ y = e["clientY"];
15898
+ }
15899
+ else if (e.touches &&
15900
+ e.touches[0] &&
15901
+ e.touches[0]["clientX"] != null &&
15902
+ e.touches[0]["clientY"] != null) {
15903
+ x = e.touches[0]["clientX"];
15904
+ y = e.touches[0]["clientY"];
15905
+ }
15906
+ else if (e.changedTouches &&
15907
+ e.changedTouches[0] &&
15908
+ e.changedTouches[0]["clientX"] != null &&
15909
+ e.changedTouches[0]["clientY"] != null) {
15910
+ x = e.changedTouches[0]["clientX"];
15911
+ y = e.changedTouches[0]["clientY"];
15912
+ }
15913
+ // @ts-ignore
15914
+ else if (e.currentPoint && e.currentPoint["x"] != null && e.currentPoint["y"] != null) {
15915
+ // @ts-ignore
15916
+ x = e.currentPoint["x"];
15917
+ // @ts-ignore
15918
+ y = e.currentPoint["y"];
15919
+ }
15920
+ return [x, y];
15921
+ }
15922
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`Window`, `boolean`, `(e: MouseEvent | TouchEvent) => boolean`, `(e: MouseEvent | TouchEvent) => void`, `(e: MouseEvent | TouchEvent) => void`, `(e: MouseEvent | TouchEvent, gesture: SwipeGesture) => void`]; }
15923
+ }
15924
+
15925
+ /**
15926
+ * adult: null
15927
+ * availability: 1
15928
+ * coverUrl: "https://cdn.test.inappstory.com/np/file/cf/wb/wc/vcaji5clqon3nkwdwle3cjz63x.jpg?k=KgAAAAAAAAACAQ"
15929
+ * currency: "RUR"
15930
+ * description: "Непромокаемый комбинезон - дождевик детский Муссон"
15931
+ * id: 204
15932
+ * name: "Непромокаемый комбинезон - дождевик детский \"Муссон\""
15933
+ * offerId: "10125"
15934
+ * oldPrice: null
15935
+ * price: "2690.0000"
15936
+ * url: "http://www.songnomik.ru/products/detskaya-odezhda-optom-dlya-novorozhdennyh/detskie-kombinezony-optom/2166483.html"
15937
+ */
15938
+ class WidgetProducts extends WidgetBase {
15939
+ static DEFAULTS = {
15940
+ slide: null,
15941
+ activateAfterCreate: false,
15942
+ create: false,
15943
+ localData: {},
15944
+ };
15945
+ static widgetClassName = "narrative-element-products";
15946
+ captionView;
15947
+ linkTarget = [];
15948
+ msgNetworkError;
15949
+ msgServiceError;
15950
+ swipeGestureDetector = null;
15951
+ isClickCapturedByWidget = false;
15952
+ isScreenSupportsTouch = false;
15953
+ constructor(element, options) {
15954
+ super(element, options);
15955
+ this.captionView = this.element.querySelector(".narrative-element-text-lines");
15956
+ const linkTarget = decodeURIComponent(getTagData(element, "linkTarget") ?? "[]");
15957
+ try {
15958
+ let parsed = JSON.parse(linkTarget);
15959
+ if (Array.isArray(parsed)) {
15960
+ this.linkTarget = parsed.filter(FilterNumber);
15961
+ }
15962
+ }
15963
+ catch (e) {
15964
+ console.error(e);
15965
+ }
15966
+ this.isScreenSupportsTouch = isScreenSupportsTouch(this.env);
15967
+ this.msgNetworkError = getTagData(this.element, "msgNetworkError");
15968
+ this.msgServiceError = getTagData(this.element, "msgServiceError");
15969
+ }
15970
+ /**
15971
+ * Start or restart widget
15972
+ * @param localData
15973
+ */
15974
+ onRefreshUserData(localData) {
15975
+ super.onRefreshUserData(localData);
15976
+ }
15977
+ onStart() {
15978
+ super.onStart();
15979
+ // reinit for case when we returned to slide from other slide and onStop destroyed SwipeGestureDetector
15980
+ this.initSwipeGestureDetector();
15981
+ }
15982
+ isTransparentElement() {
15983
+ if (this.element) {
15984
+ try {
15985
+ const color = window.getComputedStyle(this.element).color;
15986
+ if (color === "transparent" || color === "rgba(0, 0, 0, 0)" || color === "rgba(0,0,0,0)") {
15987
+ return true;
15988
+ }
15989
+ }
15990
+ catch (err) {
15991
+ console.error(err);
15992
+ }
15993
+ }
15994
+ return false;
15995
+ }
15996
+ _statEventWidgetClick() {
15997
+ try {
15998
+ const captionViewText = this.captionView?.textContent ?? "";
15999
+ this.sendStatisticEventToApp("w-products-click", {
16000
+ ...this.statisticEventBaseFieldsShortForm,
16001
+ wi: this.elementId,
16002
+ wl: captionViewText,
16003
+ wv: this.linkTarget,
16004
+ }, {
16005
+ ...this.statisticEventBaseFieldsShortForm,
16006
+ widget_id: this.elementId,
16007
+ widget_label: captionViewText,
16008
+ widget_value: this.linkTarget,
16009
+ }, {
16010
+ forceEnableStatisticV2: true,
16011
+ });
16012
+ }
16013
+ catch (error) {
16014
+ console.error(error);
16015
+ }
16016
+ }
16017
+ _statEventWidgetOpen(offers) {
16018
+ try {
16019
+ const captionViewText = this.captionView?.textContent ?? "";
16020
+ this.sendStatisticEventToApp("w-products-open", {
16021
+ ...this.statisticEventBaseFieldsShortForm,
16022
+ wi: this.elementId,
16023
+ wl: captionViewText,
16024
+ wv: this.linkTarget,
16025
+ wit: offers.map(item => item.offerId),
16026
+ }, {
16027
+ ...this.statisticEventBaseFieldsShortForm,
16028
+ widget_id: this.elementId,
16029
+ widget_label: captionViewText,
16030
+ widget_value: this.linkTarget,
16031
+ widget_items: offers.map(item => item.offerId),
16032
+ }, {
16033
+ forceEnableStatisticV2: true,
16034
+ });
16035
+ }
16036
+ catch (error) {
16037
+ console.error(error);
16038
+ }
16039
+ }
16040
+ _statEventWidgetCardClick(offer) {
16041
+ try {
16042
+ const captionViewText = this.captionView?.textContent ?? "";
16043
+ this.sendStatisticEventToApp("w-products-card-click", {
16044
+ ...this.statisticEventBaseFieldsShortForm,
16045
+ wi: this.elementId,
16046
+ wl: captionViewText,
16047
+ wv: offer.offerId,
16048
+ wvi: offer.id,
16049
+ }, {
16050
+ ...this.statisticEventBaseFieldsShortForm,
16051
+ widget_id: this.elementId,
16052
+ widget_label: captionViewText,
16053
+ widget_value: offer.offerId,
16054
+ widget_value_id: offer.id,
16055
+ }, {
16056
+ forceEnableStatisticV2: true,
16057
+ });
16058
+ }
16059
+ catch (error) {
16060
+ console.error(error);
16061
+ }
16062
+ }
16063
+ async fetchProducts() {
16064
+ const fetchAndCacheMedia = async () => {
16065
+ if (!this.linkTarget.length) {
16066
+ return { message: this.msgServiceError ?? "", models: [] };
16067
+ }
16068
+ const path = `product/offer?id=${this.linkTarget.join(",")}`;
16069
+ const headers = {
16070
+ accept: "application/json",
16071
+ "Content-Type": "application/json",
16072
+ };
16073
+ const profileKey = "fetch-products";
16074
+ try {
16075
+ const response = await this.sdkApi.sendApiRequest(path, "GET", null, headers, null, profileKey);
16076
+ // console.log({response});
16077
+ const status = response.status;
16078
+ if (status === 200 || status === 201) {
16079
+ if (response.data && Array.isArray(response.data) && response.data.length > 0) {
16080
+ try {
16081
+ await this.cacheOffersMediaResources(response.data);
16082
+ }
16083
+ catch (error) {
16084
+ console.error(error);
16085
+ }
16086
+ return { message: "", models: response.data };
16087
+ }
16088
+ else {
16089
+ return { message: this.msgServiceError ?? "", models: [] };
16090
+ }
16091
+ }
16092
+ else if (status === 12163 || status === 12002) {
16093
+ return { message: this.msgNetworkError ?? "", models: [] };
16094
+ }
16095
+ else {
16096
+ return { message: this.msgServiceError ?? "", models: [] };
16097
+ }
16098
+ }
16099
+ catch (error) {
16100
+ console.error(error);
16101
+ return { message: this.msgServiceError ?? "", models: [] };
16102
+ }
16103
+ };
16104
+ return Promise.all([
16105
+ fetchAndCacheMedia(),
16106
+ new Promise(t => {
16107
+ return setTimeout(t, 200);
16108
+ }),
16109
+ ]).then(([result]) => result);
16110
+ }
16111
+ cacheOffersMediaResources(offers) {
16112
+ const cacheItem = (offer) => {
16113
+ return new Promise(resolve => {
16114
+ if (offer.coverUrl != null) {
16115
+ this.env
16116
+ .fetch(offer.coverUrl)
16117
+ .then(response => {
16118
+ if (response != null && response.ok) {
16119
+ response
16120
+ .blob()
16121
+ .then(blob => {
16122
+ offer.coverUrl = URL.createObjectURL(blob);
16123
+ resolve();
16124
+ })
16125
+ .catch(resolve);
16126
+ }
16127
+ else {
16128
+ resolve();
16129
+ }
16130
+ })
16131
+ .catch(resolve);
16132
+ }
16133
+ else {
16134
+ resolve();
16135
+ }
16136
+ });
16137
+ };
16138
+ const promises = offers.map(cacheItem);
16139
+ return Promise.all(promises);
16140
+ }
16141
+ revokeOffersMediaResources(offers) {
16142
+ offers.forEach(offer => {
16143
+ if (offer.coverUrl != null) {
16144
+ // todo check if coverUrl really is object URL
16145
+ URL.revokeObjectURL(offer.coverUrl);
16146
+ }
16147
+ });
16148
+ }
16149
+ initSwipeGestureDetector() {
16150
+ if (this.isOpen) {
16151
+ this.swipeGestureDetector = new SwipeGestureDetector(this.env, this.isScreenSupportsTouch, () => true, e => {
16152
+ // this.isClickCapturedByWidget = true;
16153
+ return;
16154
+ }, e => {
16155
+ return;
16156
+ }, (e, gesture) => {
16157
+ if (gesture === 3 /* SwipeGesture.SwipeDown */) {
16158
+ this.closeProductsView();
16159
+ }
16160
+ // this.env.requestAnimationFrame(() => {
16161
+ // this.isClickCapturedByWidget = false;
16162
+ // });
16163
+ });
16164
+ }
16165
+ }
16166
+ productsView = null;
16167
+ isOpen = false;
16168
+ currentModels = [];
16169
+ async openProductsView() {
16170
+ if (this.isOpen) {
16171
+ return;
16172
+ }
16173
+ this._statEventWidgetClick();
16174
+ if (!this.disableTimer) {
16175
+ this.sdkApi.pauseUI();
16176
+ }
16177
+ if (!this.isTransparentElement()) {
16178
+ this.element.classList.add("loader");
16179
+ }
16180
+ // const start = window.performance.now();
16181
+ const result = await this.fetchProducts();
16182
+ // @ts-ignore
16183
+ // _log(`fetched for ${window.performance.now() - start}ms`, true);
16184
+ // console.log({result})
16185
+ if (result.models.length > 0) {
16186
+ this.currentModels = result.models;
16187
+ this.productsView = this.createProductsView(this.currentModels, this.closeProductsView.bind(this));
16188
+ this.productsView.classList.add("ias-products-container-view--visible");
16189
+ this.slide.appendChild(this.productsView);
16190
+ this.element.classList.add("hidden");
16191
+ this.isOpen = true;
16192
+ // prevent next slide navigation gesture
16193
+ this.isClickCapturedByWidget = true;
16194
+ this.sdkApi.disableVerticalSwipeGesture();
16195
+ this.sdkApi.disableBackpress();
16196
+ this._statEventWidgetOpen(this.currentModels);
16197
+ this.initSwipeGestureDetector();
16198
+ }
16199
+ else {
16200
+ if (result.message) {
16201
+ this.sdkApi.showToast(result.message);
16202
+ }
16203
+ }
16204
+ this.element.classList.remove("loader");
16205
+ }
16206
+ closeProductsView() {
16207
+ if (!this.isOpen) {
16208
+ return;
16209
+ }
16210
+ this.productsView?.classList.add("ias-products-container-view--hidden");
16211
+ this.element.classList.remove("hidden");
16212
+ this.isClickCapturedByWidget = false;
16213
+ if (this.swipeGestureDetector != null) {
16214
+ this.swipeGestureDetector.destroy();
16215
+ }
16216
+ this.sdkApi.enableVerticalSwipeGesture();
16217
+ this.sdkApi.enableBackpress();
16218
+ const onClosed = () => {
16219
+ this.productsView?.removeEventListener("animationend", onClosed);
16220
+ this.productsView?.parentElement?.removeChild(this.productsView);
16221
+ this.revokeOffersMediaResources(this.currentModels);
16222
+ if (!this.disableTimer) {
16223
+ this.sdkApi.resumeUI();
16224
+ }
16225
+ this.isOpen = false;
16226
+ this.currentModels = [];
16227
+ };
16228
+ this.productsView?.addEventListener("animationend", onClosed);
16229
+ }
16230
+ createCardView(offer) {
16231
+ const figure = document.createElement("div");
16232
+ figure.classList.add("ias-products-card-figure");
16233
+ if (offer.coverUrl) {
16234
+ // todo preload coverImage by fetch, save to offer.coverUrl via createUrl (add revoke)
16235
+ // if cannot fetch - skip caching
16236
+ const image = document.createElement("img");
16237
+ image.classList.add("ias-products-card-figure-image");
16238
+ image.alt = offer.name ?? "";
16239
+ image.src = offer.coverUrl;
16240
+ figure.appendChild(image);
16241
+ }
16242
+ // const subTitle = document.createElement("div");
16243
+ // subTitle.classList.add("ias-products-card-subtitle");
16244
+ // subTitle.innerText = offer.description ?? "";
16245
+ const title = document.createElement("div");
16246
+ title.classList.add("ias-products-card-title");
16247
+ title.innerText = offer.name ?? "";
16248
+ let price = null;
16249
+ if (offer.price) {
16250
+ price = document.createElement("div");
16251
+ price.classList.add("ias-products-card-price");
16252
+ price.innerHTML = formatter.asCurrency(offer.price, offer.currency);
16253
+ }
16254
+ let oldPrice = null;
16255
+ if (offer.oldPrice) {
16256
+ oldPrice = document.createElement("div");
16257
+ oldPrice.classList.add("ias-products-card-old-price");
16258
+ oldPrice.innerHTML = formatter.asCurrency(offer.oldPrice, offer.currency);
16259
+ }
16260
+ const prices = document.createElement("div");
16261
+ prices.classList.add("ias-products-card-prices");
16262
+ if (price) {
16263
+ prices.appendChild(price);
16264
+ }
16265
+ if (oldPrice) {
16266
+ prices.appendChild(oldPrice);
16267
+ }
16268
+ const card = document.createElement("div");
16269
+ card.classList.add("ias-products-card");
16270
+ card.onclick = () => {
16271
+ this._statEventWidgetCardClick(offer);
16272
+ if (offer.url) {
16273
+ this.sdkApi.openUrl(offer.url);
16274
+ }
16275
+ };
16276
+ card.appendChild(figure);
16277
+ // card.appendChild(subTitle);
16278
+ card.appendChild(prices);
16279
+ card.appendChild(title);
16280
+ return card;
16281
+ }
16282
+ createScrollView(offers) {
16283
+ const scrollView = document.createElement("div");
16284
+ scrollView.classList.add("ias-products-scroll-view");
16285
+ offers.forEach(offer => scrollView.appendChild(this.createCardView(offer)));
16286
+ return scrollView;
16287
+ }
16288
+ createProductsView(offers, onClose) {
16289
+ const containerView = document.createElement("div");
16290
+ containerView.classList.add("ias-products-container-view");
16291
+ const backdropView = document.createElement("div");
16292
+ backdropView.classList.add("ias-products-container-backdrop-view");
16293
+ backdropView.onclick = e => {
16294
+ e.preventDefault();
16295
+ e.stopPropagation();
16296
+ onClose();
16297
+ };
16298
+ const backgroundView = document.createElement("div");
16299
+ backgroundView.classList.add("ias-products-container-background-view");
16300
+ const scrollView = this.createScrollView(offers);
16301
+ const closeButton = document.createElement("div");
16302
+ closeButton.classList.add("ias-products-container-close-button");
16303
+ // fill=${ProductsWidgetOptionsDefault.productsList.closeBackgroundColor}
16304
+ closeButton.innerHTML = `<svg width="32" height="12.5" viewBox="0 0 64 25" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M56.293 1.23375C58.054 -0.41125 60.846 -0.41125 62.607 1.23375C64.464 2.96775 64.464 5.85675 62.607 7.59075L35.157 23.2288C33.396 24.8738 30.604 24.8738 28.843 23.2288L1.393 7.59075C0.494002 6.75175 0 5.62775 0 4.41275C0 3.19775 0.494002 2.07375 1.393 1.23475C3.154 -0.410251 5.946 -0.410251 7.707 1.23475L32 13.9237L56.293 1.23375Z" fill="currentColor" /></svg>`;
16305
+ closeButton.onclick = e => {
16306
+ e.preventDefault();
16307
+ e.stopPropagation();
16308
+ onClose();
16309
+ };
16310
+ backgroundView.appendChild(scrollView);
16311
+ backgroundView.appendChild(closeButton);
16312
+ containerView.appendChild(backdropView);
16313
+ containerView.appendChild(backgroundView);
16314
+ return containerView;
16315
+ }
16316
+ getIsClickCapturedByWidget() {
16317
+ return this.isClickCapturedByWidget;
16318
+ }
16319
+ destroy() {
16320
+ if (this.swipeGestureDetector != null) {
16321
+ this.swipeGestureDetector.destroy();
16322
+ this.swipeGestureDetector = null;
16323
+ }
16324
+ }
16325
+ onStop() {
16326
+ super.onStop();
16327
+ this.destroy();
16328
+ }
16329
+ static api = {
16330
+ widgetClassName: WidgetProducts.widgetClassName,
16331
+ onRefreshUserData: WidgetProducts.onRefreshUserData,
16332
+ init: function (element, localData) {
16333
+ WidgetProducts.initWidget(element, localData, (element, options) => new WidgetProducts(element, options));
16334
+ },
16335
+ onStart: function (element) {
16336
+ WidgetProducts.getInstance(element)?.onStart();
16337
+ },
16338
+ onStop: function (element) {
16339
+ WidgetProducts.getInstance(element)?.onStop();
16340
+ },
16341
+ click: function (element) {
16342
+ const widgetElement = element.closest(`.${WidgetProducts.widgetClassName}`);
16343
+ if (widgetElement) {
16344
+ const widget = WidgetProducts.getInstance(widgetElement);
16345
+ if (widget) {
16346
+ widget.openProductsView();
16347
+ }
16348
+ }
16349
+ return false;
16350
+ },
16351
+ isClickCapturedByWidget: function (element) {
16352
+ const widgetElement = element.closest(`.${WidgetProducts.widgetClassName}`);
16353
+ if (widgetElement) {
16354
+ const widget = WidgetProducts.getInstance(widgetElement);
16355
+ if (widget) {
16356
+ return widget.getIsClickCapturedByWidget();
16357
+ }
16358
+ }
16359
+ return false;
16360
+ },
16361
+ onHandleBackpress: function (element) {
16362
+ const widgetElement = element.closest(`.${WidgetProducts.widgetClassName}`);
16363
+ if (widgetElement) {
16364
+ const widget = WidgetProducts.getInstance(widgetElement);
16365
+ if (widget) {
16366
+ widget.closeProductsView();
16367
+ }
16368
+ }
16369
+ return false;
16370
+ },
16371
+ };
16372
+ static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
16373
+ }
16374
+
15100
16375
  let sdkInterface;
15101
16376
  const getSlideApi = (_sdkInterface) => {
15102
16377
  sdkInterface = _sdkInterface;
@@ -15117,6 +16392,7 @@ const getSlideApi = (_sdkInterface) => {
15117
16392
  WidgetTest: WidgetTest.api,
15118
16393
  WidgetVote: WidgetVote.api,
15119
16394
  WidgetBarcode: WidgetBarcode.api,
16395
+ WidgetProducts: WidgetProducts.api,
15120
16396
  };
15121
16397
  };
15122
16398