@inappstory/slide-api 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/index.cjs.d.ts +372 -0
- package/index.cjs.js +4913 -0
- package/index.d.ts +372 -0
- package/index.esm.d.ts +372 -0
- package/index.esm.js +4911 -0
- package/package.json +15 -0
package/index.cjs.js
ADDED
|
@@ -0,0 +1,4913 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const arPrototype = Array.prototype;
|
|
4
|
+
const obPrototype = Object.prototype;
|
|
5
|
+
const slice = arPrototype.slice;
|
|
6
|
+
const obKeys = Object.keys;
|
|
7
|
+
const obHasOwnProp = obPrototype.hasOwnProperty;
|
|
8
|
+
const toString = obPrototype.toString;
|
|
9
|
+
const isArray = Array.isArray ||
|
|
10
|
+
function (e) {
|
|
11
|
+
return toString.call(e) === "[object Array]";
|
|
12
|
+
};
|
|
13
|
+
// Matches dashed string for camelizing
|
|
14
|
+
const rmsPrefix = /^-ms-/;
|
|
15
|
+
const rdashAlpha = /-([\da-z])/gi;
|
|
16
|
+
const fcamelCase = function (letter) {
|
|
17
|
+
return letter.toUpperCase();
|
|
18
|
+
};
|
|
19
|
+
// private methods
|
|
20
|
+
const isObject = function (e) {
|
|
21
|
+
var t = typeof e;
|
|
22
|
+
return t === "function" || (t === "object" && !!e);
|
|
23
|
+
};
|
|
24
|
+
const isNumber = function (t) {
|
|
25
|
+
return toString.call(t) === "[object Number]";
|
|
26
|
+
};
|
|
27
|
+
const isNumeric = function (n) {
|
|
28
|
+
return !isNaN(parseFloat(n)) && isFinite(n);
|
|
29
|
+
};
|
|
30
|
+
// isEmpty = function(e) {
|
|
31
|
+
// if (e == null)
|
|
32
|
+
// return !0;
|
|
33
|
+
// if (isArray(e) || isString(e) || isArguments(e))
|
|
34
|
+
// return e.length === 0;
|
|
35
|
+
// for (var t in e)
|
|
36
|
+
// if (p.has(e, t))
|
|
37
|
+
// return !1;
|
|
38
|
+
// return !0
|
|
39
|
+
// },
|
|
40
|
+
const has = function (e, t) {
|
|
41
|
+
return e != null && obHasOwnProp.call(e, t);
|
|
42
|
+
};
|
|
43
|
+
const keys = function (e) {
|
|
44
|
+
if (!isObject(e))
|
|
45
|
+
return [];
|
|
46
|
+
if (obKeys)
|
|
47
|
+
return obKeys(e);
|
|
48
|
+
var t = [];
|
|
49
|
+
for (var n in e)
|
|
50
|
+
has(e, n) && t.push(n);
|
|
51
|
+
return t;
|
|
52
|
+
};
|
|
53
|
+
const d = function (e, t, n) {
|
|
54
|
+
if (t === void 0)
|
|
55
|
+
return e;
|
|
56
|
+
switch (3 ) {
|
|
57
|
+
case 1:
|
|
58
|
+
return function (n) {
|
|
59
|
+
return e.call(t, n);
|
|
60
|
+
};
|
|
61
|
+
case 2:
|
|
62
|
+
return function (n, r) {
|
|
63
|
+
return e.call(t, n, r);
|
|
64
|
+
};
|
|
65
|
+
case 3:
|
|
66
|
+
return function (n, r, i) {
|
|
67
|
+
return e.call(t, n, r, i);
|
|
68
|
+
};
|
|
69
|
+
case 4:
|
|
70
|
+
return function (n, r, i, s) {
|
|
71
|
+
return e.call(t, n, r, i, s);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return function () {
|
|
75
|
+
return e.apply(t, arguments);
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
const each = function (e, t, n) {
|
|
79
|
+
if (e == null)
|
|
80
|
+
return e;
|
|
81
|
+
t = d(t, n);
|
|
82
|
+
var r, i = e.length;
|
|
83
|
+
if (i === +i)
|
|
84
|
+
for (r = 0; r < i; ++r)
|
|
85
|
+
t(e[r], r, e);
|
|
86
|
+
else {
|
|
87
|
+
var s = keys(e);
|
|
88
|
+
for (r = 0, i = s.length; r < i; ++r)
|
|
89
|
+
t(e[s[r]], s[r], e);
|
|
90
|
+
}
|
|
91
|
+
return e;
|
|
92
|
+
};
|
|
93
|
+
const forEach = each;
|
|
94
|
+
const extend = function (e, ...args) {
|
|
95
|
+
var t, n;
|
|
96
|
+
for (var r = 1, i = arguments.length; r < i; r++) {
|
|
97
|
+
t = arguments[r];
|
|
98
|
+
for (n in t)
|
|
99
|
+
obHasOwnProp.call(t, n) && (e[n] = t[n]);
|
|
100
|
+
}
|
|
101
|
+
return e;
|
|
102
|
+
};
|
|
103
|
+
const isEmptyObject = function (obj) {
|
|
104
|
+
var name;
|
|
105
|
+
for (name in obj) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
return true;
|
|
109
|
+
};
|
|
110
|
+
const expando = function () {
|
|
111
|
+
return "app" + ("" + Math.random()).replace(/\D/g, "");
|
|
112
|
+
};
|
|
113
|
+
// Convert dashed to camelCase; used by the css and data modules
|
|
114
|
+
// Support: IE9-11+
|
|
115
|
+
// Microsoft forgot to hump their vendor prefix (#9572)
|
|
116
|
+
const camelCase = function (string) {
|
|
117
|
+
return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase);
|
|
118
|
+
};
|
|
119
|
+
const proxy = function (func, obj) {
|
|
120
|
+
if (typeof func != "function") {
|
|
121
|
+
return func;
|
|
122
|
+
}
|
|
123
|
+
// If obj is empty or another set another object
|
|
124
|
+
if (!obj) {
|
|
125
|
+
// @ts-ignore
|
|
126
|
+
obj = this;
|
|
127
|
+
}
|
|
128
|
+
return function () {
|
|
129
|
+
return func.apply(obj, arguments);
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
/*
|
|
133
|
+
hasData: function( elem ) {
|
|
134
|
+
return data_user.hasData( elem ) || data_priv.hasData( elem );
|
|
135
|
+
},
|
|
136
|
+
|
|
137
|
+
data: function( elem, name, data ) {
|
|
138
|
+
return data_user.access( elem, name, data );
|
|
139
|
+
},
|
|
140
|
+
|
|
141
|
+
removeData: function( elem, name ) {
|
|
142
|
+
data_user.remove( elem, name );
|
|
143
|
+
},
|
|
144
|
+
*/
|
|
145
|
+
const data = function (elem, name, data) {
|
|
146
|
+
return data_user.access(elem, name, data);
|
|
147
|
+
};
|
|
148
|
+
const getTagData = function (element, key) {
|
|
149
|
+
return element.dataset[key];
|
|
150
|
+
};
|
|
151
|
+
const getTagDataAsNumber = function (element, key) {
|
|
152
|
+
const data = element.dataset[key];
|
|
153
|
+
if (data == null) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return parseInt(data);
|
|
157
|
+
};
|
|
158
|
+
var rnotwhite = /\S+/g;
|
|
159
|
+
class Data {
|
|
160
|
+
static uid = 1;
|
|
161
|
+
static accepts(owner) {
|
|
162
|
+
// Accepts only:
|
|
163
|
+
// - Node
|
|
164
|
+
// - Node.ELEMENT_NODE
|
|
165
|
+
// - Node.DOCUMENT_NODE
|
|
166
|
+
// - Object
|
|
167
|
+
// - Any
|
|
168
|
+
/* jshint -W018 */
|
|
169
|
+
return owner.nodeType === 1 || owner.nodeType === 9 || !+owner.nodeType;
|
|
170
|
+
}
|
|
171
|
+
expando;
|
|
172
|
+
cache;
|
|
173
|
+
constructor() {
|
|
174
|
+
// Support: Android<4,
|
|
175
|
+
// Old WebKit does not have Object.preventExtensions/freeze method,
|
|
176
|
+
// return new empty object instead with no [[set]] accessor
|
|
177
|
+
Object.defineProperty((this.cache = {}), 0, {
|
|
178
|
+
get: function () {
|
|
179
|
+
return {};
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
this.expando = expando() + String(Data.uid++);
|
|
183
|
+
}
|
|
184
|
+
key(owner) {
|
|
185
|
+
const _owner = owner;
|
|
186
|
+
// We can accept data for non-element nodes in modern browsers,
|
|
187
|
+
// but we should not, see #8335.
|
|
188
|
+
// Always return the key for a frozen object.
|
|
189
|
+
if (!Data.accepts(_owner)) {
|
|
190
|
+
return 0;
|
|
191
|
+
}
|
|
192
|
+
var descriptor = {},
|
|
193
|
+
// Check if the owner object already has a cache key
|
|
194
|
+
unlock = _owner[this.expando];
|
|
195
|
+
// If not, create one
|
|
196
|
+
if (!unlock) {
|
|
197
|
+
unlock = Data.uid++;
|
|
198
|
+
// Secure it in a non-enumerable, non-writable property
|
|
199
|
+
try {
|
|
200
|
+
descriptor[this.expando] = { value: unlock };
|
|
201
|
+
Object.defineProperties(_owner, descriptor);
|
|
202
|
+
// Support: Android<4
|
|
203
|
+
// Fallback to a less secure definition
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
descriptor[this.expando] = unlock;
|
|
207
|
+
extend(_owner, descriptor);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Ensure the cache object
|
|
211
|
+
if (!this.cache[unlock]) {
|
|
212
|
+
this.cache[unlock] = {};
|
|
213
|
+
}
|
|
214
|
+
return unlock;
|
|
215
|
+
}
|
|
216
|
+
set(owner, data, value) {
|
|
217
|
+
var prop,
|
|
218
|
+
// There may be an unlock assigned to this node,
|
|
219
|
+
// if there is no entry for this "owner", create one inline
|
|
220
|
+
// and set the unlock as though an owner entry had always existed
|
|
221
|
+
unlock = this.key(owner), cache = this.cache[unlock];
|
|
222
|
+
// Handle: [ owner, key, value ] args
|
|
223
|
+
if (typeof data === "string") {
|
|
224
|
+
cache[data] = value;
|
|
225
|
+
// Handle: [ owner, { properties } ] args
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// Fresh assignments by object are shallow copied
|
|
229
|
+
if (isEmptyObject(cache)) {
|
|
230
|
+
extend(this.cache[unlock], data);
|
|
231
|
+
// Otherwise, copy the properties one-by-one to the cache object
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
for (prop in data) {
|
|
235
|
+
//@ts-ignore
|
|
236
|
+
cache[prop] = data[prop];
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return cache;
|
|
241
|
+
}
|
|
242
|
+
get(owner, key) {
|
|
243
|
+
// Either a valid cache is found, or will be created.
|
|
244
|
+
// New caches will be created and the unlock returned,
|
|
245
|
+
// allowing direct access to the newly created
|
|
246
|
+
// empty data object. A valid owner object must be provided.
|
|
247
|
+
var cache = this.cache[this.key(owner)];
|
|
248
|
+
return key === undefined ? cache : cache[key];
|
|
249
|
+
}
|
|
250
|
+
access(owner, key, value) {
|
|
251
|
+
var stored;
|
|
252
|
+
// In cases where either:
|
|
253
|
+
//
|
|
254
|
+
// 1. No key was specified
|
|
255
|
+
// 2. A string key was specified, but no value provided
|
|
256
|
+
//
|
|
257
|
+
// Take the "read" path and allow the get method to determine
|
|
258
|
+
// which value to return, respectively either:
|
|
259
|
+
//
|
|
260
|
+
// 1. The entire cache object
|
|
261
|
+
// 2. The data stored at the key
|
|
262
|
+
//
|
|
263
|
+
if (key === undefined || (key && typeof key === "string" && value === undefined)) {
|
|
264
|
+
stored = this.get(owner, key);
|
|
265
|
+
return stored !== undefined ? stored : this.get(owner, camelCase(key));
|
|
266
|
+
}
|
|
267
|
+
// [*]When the key is not a string, or both a key and value
|
|
268
|
+
// are specified, set or extend (existing objects) with either:
|
|
269
|
+
//
|
|
270
|
+
// 1. An object of properties
|
|
271
|
+
// 2. A key and value
|
|
272
|
+
//
|
|
273
|
+
this.set(owner, key, value);
|
|
274
|
+
// Since the "set" path can have two possible entry points
|
|
275
|
+
// return the expected data based on which path was taken[*]
|
|
276
|
+
return value !== undefined ? value : key;
|
|
277
|
+
}
|
|
278
|
+
remove(owner, key) {
|
|
279
|
+
var i, name, camel, unlock = this.key(owner), cache = this.cache[unlock];
|
|
280
|
+
if (key === undefined) {
|
|
281
|
+
this.cache[unlock] = {};
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
// Support array or space separated string of keys
|
|
285
|
+
if (isArray(key)) {
|
|
286
|
+
// If "name" is an array of keys...
|
|
287
|
+
// When data is initially created, via ("key", "val") signature,
|
|
288
|
+
// keys will be converted to camelCase.
|
|
289
|
+
// Since there is no way to tell _how_ a key was added, remove
|
|
290
|
+
// both plain key and camelCase key. #12786
|
|
291
|
+
// This will only penalize the array argument path.
|
|
292
|
+
name = key.concat(key.map(camelCase));
|
|
293
|
+
}
|
|
294
|
+
else {
|
|
295
|
+
camel = camelCase(key);
|
|
296
|
+
// Try the string as a key before any manipulation
|
|
297
|
+
if (key in cache) {
|
|
298
|
+
name = [key, camel];
|
|
299
|
+
}
|
|
300
|
+
else {
|
|
301
|
+
// If a key with the spaces exists, use it.
|
|
302
|
+
// Otherwise, create an array by matching non-whitespace
|
|
303
|
+
name = camel;
|
|
304
|
+
name = name in cache ? [name] : name.match(rnotwhite) || [];
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
i = name.length;
|
|
308
|
+
while (i--) {
|
|
309
|
+
delete cache[name[i]];
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
hasData(owner) {
|
|
314
|
+
const _owner = owner;
|
|
315
|
+
return !isEmptyObject(this.cache[_owner[this.expando]] || {});
|
|
316
|
+
}
|
|
317
|
+
discard(owner) {
|
|
318
|
+
const _owner = owner;
|
|
319
|
+
if (_owner[this.expando]) {
|
|
320
|
+
delete this.cache[_owner[this.expando]];
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return []; }
|
|
324
|
+
}
|
|
325
|
+
// var data_priv = new Data();
|
|
326
|
+
const data_user = new Data();
|
|
327
|
+
const getSlideDuration = function (sdkApi, storyId, slideIndex) {
|
|
328
|
+
return sdkApi.getSlideDuration(storyId, slideIndex) ?? 10000;
|
|
329
|
+
};
|
|
330
|
+
const getWinWidth = function (env) {
|
|
331
|
+
return env.innerWidth || env.document.documentElement.clientWidth || env.document.body.clientWidth;
|
|
332
|
+
};
|
|
333
|
+
const getWinHeight = function (env) {
|
|
334
|
+
return env.innerHeight || env.document.documentElement.clientHeight || env.document.body.clientHeight;
|
|
335
|
+
};
|
|
336
|
+
const sendStatisticEventToApp = function (sdkApi, name, data, devPayload) {
|
|
337
|
+
sdkApi.sendStatisticEvent(name, data, devPayload);
|
|
338
|
+
};
|
|
339
|
+
const getValueOrException = function (value, message) {
|
|
340
|
+
if (value == null) {
|
|
341
|
+
throw new Error(message);
|
|
342
|
+
}
|
|
343
|
+
return value;
|
|
344
|
+
};
|
|
345
|
+
const getValueOrDefault = function (value, defaultValue) {
|
|
346
|
+
if (value == null) {
|
|
347
|
+
return defaultValue;
|
|
348
|
+
}
|
|
349
|
+
return value;
|
|
350
|
+
};
|
|
351
|
+
const getElementBounding = (env, rect) => {
|
|
352
|
+
var wWidth = getWinWidth(env);
|
|
353
|
+
var wHeight = getWinHeight(env);
|
|
354
|
+
var bounding = {
|
|
355
|
+
absolute: {
|
|
356
|
+
width: rect.width,
|
|
357
|
+
height: rect.height,
|
|
358
|
+
left: rect.left,
|
|
359
|
+
right: 0,
|
|
360
|
+
center: {
|
|
361
|
+
x: rect.x + rect.width / 2,
|
|
362
|
+
y: rect.y + rect.height / 2,
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
width: (rect.width / wWidth) * 100,
|
|
366
|
+
height: (rect.height / wHeight) * 100,
|
|
367
|
+
left: (rect.left / wWidth) * 100,
|
|
368
|
+
right: 0,
|
|
369
|
+
center: {
|
|
370
|
+
x: ((rect.x + rect.width / 2) / wWidth) * 100,
|
|
371
|
+
y: ((rect.y + rect.height / 2) / wHeight) * 100,
|
|
372
|
+
},
|
|
373
|
+
};
|
|
374
|
+
bounding.right = bounding.left + bounding.width;
|
|
375
|
+
bounding.absolute.right = rect.left + rect.width;
|
|
376
|
+
return bounding;
|
|
377
|
+
};
|
|
378
|
+
const toArray = (value) => Array.prototype.slice.call(value);
|
|
379
|
+
const addClass = (target, className) => {
|
|
380
|
+
var arr = target.className.split(" ");
|
|
381
|
+
if (arr.indexOf(className) === -1) {
|
|
382
|
+
target.className += " " + className;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
const removeClass = (target, className) => {
|
|
386
|
+
target.className = target.className.replace(new RegExp("(?:^|\\s)" + className + "(?:\\s|$)"), " ").trim();
|
|
387
|
+
};
|
|
388
|
+
const classList = (target) => {
|
|
389
|
+
if (target.classList !== undefined) {
|
|
390
|
+
return toArray(target.classList);
|
|
391
|
+
}
|
|
392
|
+
return target.className.split(" ");
|
|
393
|
+
};
|
|
394
|
+
const hasClass = (target, className) => classList(target).indexOf(className) !== -1;
|
|
395
|
+
const Clipboard = (function (window, document, navigator) {
|
|
396
|
+
let textArea;
|
|
397
|
+
function isOS() {
|
|
398
|
+
return navigator.userAgent.match(/ipad|iphone/i);
|
|
399
|
+
}
|
|
400
|
+
function createTextArea(text) {
|
|
401
|
+
textArea = document.createElement("textArea");
|
|
402
|
+
textArea.value = text;
|
|
403
|
+
document.body.appendChild(textArea);
|
|
404
|
+
}
|
|
405
|
+
function selectText() {
|
|
406
|
+
if (isOS()) {
|
|
407
|
+
const range = document.createRange();
|
|
408
|
+
range.selectNodeContents(textArea);
|
|
409
|
+
const selection = window.getSelection();
|
|
410
|
+
if (selection) {
|
|
411
|
+
selection.removeAllRanges();
|
|
412
|
+
selection.addRange(range);
|
|
413
|
+
}
|
|
414
|
+
textArea.setSelectionRange(0, 999999);
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
textArea.select();
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function copyToClipboard() {
|
|
421
|
+
document.execCommand("copy");
|
|
422
|
+
document.body.removeChild(textArea);
|
|
423
|
+
}
|
|
424
|
+
const copy = function (text) {
|
|
425
|
+
createTextArea(text);
|
|
426
|
+
selectText();
|
|
427
|
+
copyToClipboard();
|
|
428
|
+
};
|
|
429
|
+
return {
|
|
430
|
+
copy,
|
|
431
|
+
};
|
|
432
|
+
})(window, document, navigator);
|
|
433
|
+
|
|
434
|
+
var supportAnimate = document.documentElement.animate !== undefined;
|
|
435
|
+
supportAnimate = false; // tmp off
|
|
436
|
+
var _intervals = [];
|
|
437
|
+
var _startShakeAnimation = function (element) {
|
|
438
|
+
var step = 0;
|
|
439
|
+
return window.setInterval(function () {
|
|
440
|
+
if (element) {
|
|
441
|
+
switch (step) {
|
|
442
|
+
case 0:
|
|
443
|
+
element.style.setProperty("transform", "translate(1px, 1px) rotate(0deg)");
|
|
444
|
+
break;
|
|
445
|
+
case 10:
|
|
446
|
+
element.style.setProperty("transform", "translate(-1px, -2px) rotate(-1deg)");
|
|
447
|
+
break;
|
|
448
|
+
case 20:
|
|
449
|
+
element.style.setProperty("transform", "translate(-3px, 0px) rotate(1deg)");
|
|
450
|
+
break;
|
|
451
|
+
case 30:
|
|
452
|
+
element.style.setProperty("transform", "translate(3px, 2px) rotate(0deg)");
|
|
453
|
+
break;
|
|
454
|
+
case 40:
|
|
455
|
+
element.style.setProperty("transform", "translate(1px, -1px) rotate(1deg)");
|
|
456
|
+
break;
|
|
457
|
+
case 50:
|
|
458
|
+
element.style.setProperty("transform", "translate(-1px, 2px) rotate(-1deg)");
|
|
459
|
+
break;
|
|
460
|
+
case 60:
|
|
461
|
+
element.style.setProperty("transform", "translate(-3px, 1px) rotate(0deg)");
|
|
462
|
+
break;
|
|
463
|
+
case 70:
|
|
464
|
+
element.style.setProperty("transform", "translate(-3px, 1px) rotate(0deg)");
|
|
465
|
+
break;
|
|
466
|
+
case 80:
|
|
467
|
+
element.style.setProperty("transform", "translate(-1px, -1px) rotate(1deg)");
|
|
468
|
+
break;
|
|
469
|
+
case 90:
|
|
470
|
+
element.style.setProperty("transform", "translate(1px, 2px) rotate(0deg)");
|
|
471
|
+
break;
|
|
472
|
+
case 100:
|
|
473
|
+
element.style.setProperty("transform", "translate(1px, -2px) rotate(-1deg)");
|
|
474
|
+
break;
|
|
475
|
+
}
|
|
476
|
+
step += 10;
|
|
477
|
+
if (step > 100) {
|
|
478
|
+
step = 0;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
}, 100);
|
|
482
|
+
};
|
|
483
|
+
var _startExpandShakeAnimation = function (element) {
|
|
484
|
+
var step = 0;
|
|
485
|
+
return window.setInterval(function () {
|
|
486
|
+
if (element) {
|
|
487
|
+
switch (step) {
|
|
488
|
+
case 0:
|
|
489
|
+
element.style.setProperty("transform", "translate(1px, 1px) rotate(0deg) scale(1.1)");
|
|
490
|
+
break;
|
|
491
|
+
case 10:
|
|
492
|
+
element.style.setProperty("transform", "translate(-1px, -2px) rotate(-1deg) scale(1.1)");
|
|
493
|
+
break;
|
|
494
|
+
case 20:
|
|
495
|
+
element.style.setProperty("transform", "translate(-3px, 0px) rotate(1deg) scale(1.1)");
|
|
496
|
+
break;
|
|
497
|
+
case 30:
|
|
498
|
+
element.style.setProperty("transform", "translate(3px, 2px) rotate(0deg) scale(1.1)");
|
|
499
|
+
break;
|
|
500
|
+
case 40:
|
|
501
|
+
element.style.setProperty("transform", "translate(1px, -1px) rotate(1deg) scale(1.1)");
|
|
502
|
+
break;
|
|
503
|
+
case 50:
|
|
504
|
+
element.style.setProperty("transform", "translate(-1px, 2px) rotate(-1deg) scale(1.1)");
|
|
505
|
+
break;
|
|
506
|
+
case 60:
|
|
507
|
+
element.style.setProperty("transform", "translate(-3px, 1px) rotate(0deg) scale(1.1)");
|
|
508
|
+
break;
|
|
509
|
+
case 70:
|
|
510
|
+
element.style.setProperty("transform", "translate(3px, 1px) rotate(-1deg) scale(1.1)");
|
|
511
|
+
break;
|
|
512
|
+
case 80:
|
|
513
|
+
element.style.setProperty("transform", "translate(-1px, -1px) rotate(1deg) scale(1.1)");
|
|
514
|
+
break;
|
|
515
|
+
case 90:
|
|
516
|
+
element.style.setProperty("transform", "translate(1px, 2px) rotate(0deg) scale(1.1)");
|
|
517
|
+
break;
|
|
518
|
+
case 100:
|
|
519
|
+
element.style.setProperty("transform", "translate(1px, -2px) rotate(-1deg) scale(1.1)");
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
step += 10;
|
|
523
|
+
if (step > 100) {
|
|
524
|
+
step = 0;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}, 100);
|
|
528
|
+
};
|
|
529
|
+
var _startBlurAnimation = function (element) {
|
|
530
|
+
const listener = (e) => {
|
|
531
|
+
if (e.propertyName === "filter" && e.target != null) {
|
|
532
|
+
const target = e.target;
|
|
533
|
+
if (hasClass(target, "animated")) {
|
|
534
|
+
if (target.style.filter === "blur(0px)" || target.style.filter === "") {
|
|
535
|
+
setTimeout(function () {
|
|
536
|
+
target.style.filter = "blur(5px)";
|
|
537
|
+
}, 10);
|
|
538
|
+
}
|
|
539
|
+
else if (target.style.filter === "blur(5px)") {
|
|
540
|
+
setTimeout(function () {
|
|
541
|
+
target.style.filter = "blur(0px)";
|
|
542
|
+
}, 10);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
else {
|
|
546
|
+
target.style.filter = "";
|
|
547
|
+
target.removeEventListener("transitionend", listener);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
element.addEventListener("transitionend", listener);
|
|
552
|
+
};
|
|
553
|
+
var shortDuration = {
|
|
554
|
+
duration: 1000,
|
|
555
|
+
iterations: 1,
|
|
556
|
+
};
|
|
557
|
+
var longDuration = {
|
|
558
|
+
duration: 10000,
|
|
559
|
+
iterations: 1,
|
|
560
|
+
};
|
|
561
|
+
var extraLongDuration = {
|
|
562
|
+
duration: 20000,
|
|
563
|
+
iterations: 1,
|
|
564
|
+
};
|
|
565
|
+
var longInfinityDuration = {
|
|
566
|
+
duration: 10000,
|
|
567
|
+
iterations: Infinity,
|
|
568
|
+
};
|
|
569
|
+
var getAnimationFunction = function (element) {
|
|
570
|
+
if (!hasClass(element, "animated")) {
|
|
571
|
+
if (hasClass(element, "narrative-element-animation-shake")) {
|
|
572
|
+
if (element.parentElement && hasClass(element.parentElement, "narrative-element-expand")) {
|
|
573
|
+
return function () {
|
|
574
|
+
_intervals.push(_startExpandShakeAnimation(element));
|
|
575
|
+
addClass(element, "animated");
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
return function () {
|
|
580
|
+
_intervals.push(_startShakeAnimation(element));
|
|
581
|
+
addClass(element, "animated");
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
else if (hasClass(element, "narrative-element-animation-blur")) {
|
|
586
|
+
return function () {
|
|
587
|
+
_startBlurAnimation(element);
|
|
588
|
+
addClass(element, "animated");
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
return function () {
|
|
593
|
+
addClass(element, "active");
|
|
594
|
+
addClass(element, "animated");
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return function () { };
|
|
599
|
+
};
|
|
600
|
+
const animationApi = {
|
|
601
|
+
start: function (slide, animate = false) {
|
|
602
|
+
if (supportAnimate && animate) {
|
|
603
|
+
// for editor, todo add .reset-animation to narrative-editor-slide && clear that
|
|
604
|
+
if (!hasClass(slide, "narrative-slide")) {
|
|
605
|
+
addClass(slide, "reset-animation");
|
|
606
|
+
}
|
|
607
|
+
const elements = toArray(slide.querySelectorAll(".narrative-element-animation"));
|
|
608
|
+
elements.forEach(element => {
|
|
609
|
+
var width = element.offsetWidth;
|
|
610
|
+
var height = element.offsetHeight;
|
|
611
|
+
var _classList = classList(element);
|
|
612
|
+
if (_classList.indexOf("narrative-element-animation-fade-in-up") !== -1) {
|
|
613
|
+
element.animate({
|
|
614
|
+
transform: ["translateY(" + height + "px)", "translateY(0)"],
|
|
615
|
+
opacity: [0, 1],
|
|
616
|
+
}, shortDuration);
|
|
617
|
+
}
|
|
618
|
+
else if (_classList.indexOf("narrative-element-animation-fade-in-down") !== -1) {
|
|
619
|
+
element.animate({
|
|
620
|
+
transform: ["translateY(" + -1 * height + "px)", "translateY(0)"],
|
|
621
|
+
opacity: [0, 1],
|
|
622
|
+
}, shortDuration);
|
|
623
|
+
}
|
|
624
|
+
else if (_classList.indexOf("narrative-element-animation-fade-in-left") !== -1) {
|
|
625
|
+
element.animate({
|
|
626
|
+
transform: ["translateX(" + -1 * width + "px)", "translateX(0)"],
|
|
627
|
+
opacity: [0, 1],
|
|
628
|
+
}, shortDuration);
|
|
629
|
+
}
|
|
630
|
+
else if (_classList.indexOf("narrative-element-animation-fade-in-right") !== -1) {
|
|
631
|
+
element.animate({
|
|
632
|
+
transform: ["translateX(" + width + "px)", "translateX(0)"],
|
|
633
|
+
opacity: [0, 1],
|
|
634
|
+
}, shortDuration);
|
|
635
|
+
}
|
|
636
|
+
else if (_classList.indexOf("narrative-element-animation-blur") !== -1) {
|
|
637
|
+
element.animate([
|
|
638
|
+
{ filter: "blur(5px)", offset: 0 },
|
|
639
|
+
{ filter: "blur(0px)", offset: 0.5 },
|
|
640
|
+
{ filter: "blur(5px)", offset: 1 },
|
|
641
|
+
], longInfinityDuration);
|
|
642
|
+
}
|
|
643
|
+
else if (_classList.indexOf("narrative-element-animation-focus-in") !== -1) {
|
|
644
|
+
element.animate({ filter: ["blur(12px)", "blur(0px)"], opacity: [0, 1] }, shortDuration);
|
|
645
|
+
}
|
|
646
|
+
else if (_classList.indexOf("narrative-element-animation-scroll-left") !== -1) {
|
|
647
|
+
element.animate({
|
|
648
|
+
transform: ["scale(1.2) translateX(" + 0.08 * width + "px)", "scale(1.2) translateX(" + -0.08 * width + "px)"],
|
|
649
|
+
}, extraLongDuration);
|
|
650
|
+
}
|
|
651
|
+
else if (_classList.indexOf("narrative-element-animation-scroll-right") !== -1) {
|
|
652
|
+
element.animate({
|
|
653
|
+
transform: ["scale(1.2) translateX(" + -0.08 * width + "px)", "scale(1.2) translateX(" + 0.08 * width + "px)"],
|
|
654
|
+
}, extraLongDuration);
|
|
655
|
+
}
|
|
656
|
+
else if (_classList.indexOf("narrative-element-animation-scroll-up") !== -1) {
|
|
657
|
+
element.animate({
|
|
658
|
+
transform: ["scale(1.2) translateY(" + 0.08 * width + "px)", "scale(1.2) translateY(" + -0.08 * width + "px)"],
|
|
659
|
+
}, extraLongDuration);
|
|
660
|
+
}
|
|
661
|
+
else if (_classList.indexOf("narrative-element-animation-scroll-down") !== -1) {
|
|
662
|
+
element.animate({
|
|
663
|
+
transform: ["scale(1.2) translateY(" + -0.08 * width + "px)", "scale(1.2) translateY(" + 0.08 * width + "px)"],
|
|
664
|
+
}, extraLongDuration);
|
|
665
|
+
}
|
|
666
|
+
else if (_classList.indexOf("narrative-element-animation-zoom") !== -1) {
|
|
667
|
+
element.animate({ transform: ["scale(1)", "scale(1.2)"] }, longDuration);
|
|
668
|
+
}
|
|
669
|
+
else if (_classList.indexOf("narrative-element-animation-zoom-out") !== -1) {
|
|
670
|
+
element.animate({ transform: ["scale(1.2)", "scale(1)"] }, longDuration);
|
|
671
|
+
}
|
|
672
|
+
else if (_classList.indexOf("narrative-element-animation-shake") !== -1) {
|
|
673
|
+
element.animate([
|
|
674
|
+
{ transform: "translate(1px, 1px) rotate(0deg)", offset: 0 },
|
|
675
|
+
{ transform: "translate(-1px, -2px) rotate(-1deg)", offset: 0.1 },
|
|
676
|
+
{ transform: "translate(-3px, 0px) rotate(1deg)", offset: 0.2 },
|
|
677
|
+
{ transform: "translate(3px, 2px) rotate(0deg)", offset: 0.3 },
|
|
678
|
+
{ transform: "translate(1px, -1px) rotate(1deg)", offset: 0.4 },
|
|
679
|
+
{ transform: "translate(-1px, 2px) rotate(-1deg)", offset: 0.5 },
|
|
680
|
+
{ transform: "translate(-3px, 1px) rotate(0deg)", offset: 0.6 },
|
|
681
|
+
{ transform: "translate(3px, 1px) rotate(-1deg)", offset: 0.7 },
|
|
682
|
+
{ transform: "translate(-1px, -1px) rotate(1deg)", offset: 0.8 },
|
|
683
|
+
{ transform: "translate(1px, 2px) rotate(0deg)", offset: 0.9 },
|
|
684
|
+
{ transform: "translate(1px, -2px) rotate(-1deg)", offset: 1 },
|
|
685
|
+
], { duration: 1000, iterations: Infinity, composite: "add" });
|
|
686
|
+
}
|
|
687
|
+
});
|
|
688
|
+
if (elements.length > 0) {
|
|
689
|
+
requestAnimationFrame(() => removeClass(slide, "reset-animation"));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
addClass(slide, "animation-fallback");
|
|
694
|
+
const animations = [];
|
|
695
|
+
// просто Array
|
|
696
|
+
var elements = slide.querySelectorAll(".narrative-element-animation");
|
|
697
|
+
var isEditorSlide = hasClass(slide, "narrative-editor-slide");
|
|
698
|
+
for (var i = 0; i < elements.length; i++) {
|
|
699
|
+
if (!isEditorSlide && !elements[i].style.getPropertyValue("--width")) {
|
|
700
|
+
var rects = elements[i].getBoundingClientRect();
|
|
701
|
+
var width = rects.width;
|
|
702
|
+
var height = rects.height;
|
|
703
|
+
if (width && height) {
|
|
704
|
+
elements[i].style.setProperty("--width", width + "px");
|
|
705
|
+
elements[i].style.setProperty("--height", height + "px");
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
(function (element) {
|
|
709
|
+
var timeout = 50;
|
|
710
|
+
if (element.getAttribute("data-animation-timeout") && parseFloat(element.getAttribute("data-animation-timeout") ?? "0")) {
|
|
711
|
+
timeout = parseFloat(element.getAttribute("data-animation-timeout") ?? "0") * 1000;
|
|
712
|
+
}
|
|
713
|
+
const cb = () => {
|
|
714
|
+
getAnimationFunction(element)();
|
|
715
|
+
if (animation) {
|
|
716
|
+
animation.timerId = undefined;
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
const animation = {
|
|
720
|
+
cb,
|
|
721
|
+
timeout,
|
|
722
|
+
timerId: window.setTimeout(cb, timeout),
|
|
723
|
+
};
|
|
724
|
+
animations.push(animation);
|
|
725
|
+
})(elements[i]);
|
|
726
|
+
}
|
|
727
|
+
var startAt = new Date().getTime();
|
|
728
|
+
// onstop && onpause
|
|
729
|
+
return function (isStop) {
|
|
730
|
+
for (var animation of animations) {
|
|
731
|
+
if (animation["timerId"] !== undefined) {
|
|
732
|
+
clearTimeout(animation["timerId"]);
|
|
733
|
+
animation["timerId"] = undefined;
|
|
734
|
+
animation["timeout"] -= new Date().getTime() - startAt;
|
|
735
|
+
animation["needResume"] = !isStop;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
// resume
|
|
739
|
+
return function () {
|
|
740
|
+
startAt = new Date().getTime();
|
|
741
|
+
for (const animation of animations) {
|
|
742
|
+
if (animation["timerId"] === undefined && animation["needResume"] === true) {
|
|
743
|
+
animation["timerId"] = window.setTimeout(animation["cb"], animation["timeout"]);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
},
|
|
750
|
+
stop: function (slide, animate) {
|
|
751
|
+
if (supportAnimate && animate) {
|
|
752
|
+
/** @type {HTMLElement[]} */
|
|
753
|
+
var elements = toArray(slide.querySelectorAll(".narrative-element-animation"));
|
|
754
|
+
elements.forEach(function (el) {
|
|
755
|
+
el.getAnimations().forEach(function (animation) {
|
|
756
|
+
animation.cancel();
|
|
757
|
+
});
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
else {
|
|
761
|
+
for (var i = 0; i < _intervals.length; i++) {
|
|
762
|
+
clearInterval(_intervals[i]);
|
|
763
|
+
}
|
|
764
|
+
if (slide) {
|
|
765
|
+
var elements = toArray(slide.querySelectorAll(".narrative-element-animation"));
|
|
766
|
+
for (var i = 0; i < elements.length; i++) {
|
|
767
|
+
removeClass(elements[i], "active");
|
|
768
|
+
removeClass(elements[i], "animated");
|
|
769
|
+
elements[i].style.setProperty("transform", "");
|
|
770
|
+
elements[i].style.setProperty("filter", "");
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
},
|
|
775
|
+
pause: function (slide) {
|
|
776
|
+
if (supportAnimate) {
|
|
777
|
+
/* var elements = document.querySelectorAll('.narrative-element-animation');
|
|
778
|
+
elements = _toArray(elements);
|
|
779
|
+
|
|
780
|
+
elements.forEach(function(el) {
|
|
781
|
+
el.playState = "paused";
|
|
782
|
+
// el.currentTime = 0;
|
|
783
|
+
});*/
|
|
784
|
+
var elements = toArray(slide.querySelectorAll(".narrative-element-animation"));
|
|
785
|
+
elements.forEach(function (el) {
|
|
786
|
+
el.getAnimations().forEach(function (animation) {
|
|
787
|
+
if (animation.playState !== "finished" && animation.playState === "running") {
|
|
788
|
+
animation.pause();
|
|
789
|
+
}
|
|
790
|
+
});
|
|
791
|
+
});
|
|
792
|
+
// slide.getAnimations().forEach(function (animation) {
|
|
793
|
+
// if (animation.playState !== 'finished' && animation.playState === 'running') {
|
|
794
|
+
// animation.pause();
|
|
795
|
+
// }
|
|
796
|
+
// });
|
|
797
|
+
}
|
|
798
|
+
},
|
|
799
|
+
resume: function (slide) {
|
|
800
|
+
if (supportAnimate) {
|
|
801
|
+
var elements = toArray(slide.querySelectorAll(".narrative-element-animation"));
|
|
802
|
+
elements.forEach(function (el) {
|
|
803
|
+
el.getAnimations().forEach(function (animation) {
|
|
804
|
+
if (animation.playState === "paused") {
|
|
805
|
+
animation.play();
|
|
806
|
+
}
|
|
807
|
+
});
|
|
808
|
+
});
|
|
809
|
+
}
|
|
810
|
+
},
|
|
811
|
+
reset: function (slide) {
|
|
812
|
+
// _addClass(slide, 'reset-animation');
|
|
813
|
+
},
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
const CONSTRUCTOR_ARGUMENTS_SYMBOL_IDENTIFIER = `___CTOR_ARGS___`;
|
|
817
|
+
const CONSTRUCTOR_ARGUMENTS_SYMBOL = Symbol.for(CONSTRUCTOR_ARGUMENTS_SYMBOL_IDENTIFIER);
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* A Dependency-Injection container that holds services and can produce instances of them as required.
|
|
821
|
+
* It mimics reflection by parsing the app at compile-time and supporting the generic-reflection syntax.
|
|
822
|
+
* @author Frederik Wessberg
|
|
823
|
+
*/
|
|
824
|
+
class DIContainer {
|
|
825
|
+
/**
|
|
826
|
+
* A map between interface names and the services that should be dependency injected
|
|
827
|
+
*/
|
|
828
|
+
constructorArguments = new Map();
|
|
829
|
+
/**
|
|
830
|
+
* A Map between identifying names for services and their IRegistrationRecords.
|
|
831
|
+
*/
|
|
832
|
+
serviceRegistry = new Map();
|
|
833
|
+
/**
|
|
834
|
+
* A map between identifying names for services and concrete instances of their implementation.
|
|
835
|
+
*/
|
|
836
|
+
instances = new Map();
|
|
837
|
+
registerSingleton(newExpression, options) {
|
|
838
|
+
if (options == null) {
|
|
839
|
+
throw new ReferenceError(`2 arguments required, but only 0 present. ${DI_COMPILER_ERROR_HINT}`);
|
|
840
|
+
}
|
|
841
|
+
if (newExpression == null) {
|
|
842
|
+
return this.register("SINGLETON", newExpression, options);
|
|
843
|
+
}
|
|
844
|
+
else {
|
|
845
|
+
return this.register("SINGLETON", newExpression, options);
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
registerTransient(newExpression, options) {
|
|
849
|
+
if (options == null) {
|
|
850
|
+
throw new ReferenceError(`2 arguments required, but only 0 present. ${DI_COMPILER_ERROR_HINT}`);
|
|
851
|
+
}
|
|
852
|
+
if (newExpression == null) {
|
|
853
|
+
return this.register("TRANSIENT", newExpression, options);
|
|
854
|
+
}
|
|
855
|
+
else {
|
|
856
|
+
return this.register("TRANSIENT", newExpression, options);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Gets an instance of the service matching the interface given as a generic type parameter.
|
|
861
|
+
* For example, 'container.get<IFoo>()' returns a concrete instance of the implementation associated with the
|
|
862
|
+
* generic interface name.
|
|
863
|
+
*
|
|
864
|
+
* You should not pass any options to the method if using the compiler. It will do that automatically.
|
|
865
|
+
*/
|
|
866
|
+
get(options) {
|
|
867
|
+
if (options == null) {
|
|
868
|
+
throw new ReferenceError(`1 argument required, but only 0 present. ${DI_COMPILER_ERROR_HINT}`);
|
|
869
|
+
}
|
|
870
|
+
return this.constructInstance(options);
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Returns true if a service has been registered matching the interface given as a generic type parameter.
|
|
874
|
+
* For example, 'container.get<IFoo>()' returns a concrete instance of the implementation associated with the
|
|
875
|
+
* generic interface name.
|
|
876
|
+
*
|
|
877
|
+
* You should not pass any options to the method if using the compiler. It will do that automatically.
|
|
878
|
+
*/
|
|
879
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
880
|
+
has(options) {
|
|
881
|
+
if (options == null) {
|
|
882
|
+
throw new ReferenceError(`1 argument required, but only 0 present. ${DI_COMPILER_ERROR_HINT}`);
|
|
883
|
+
}
|
|
884
|
+
return this.serviceRegistry.has(options.identifier);
|
|
885
|
+
}
|
|
886
|
+
register(kind, newExpression, options) {
|
|
887
|
+
// Take all of the constructor arguments for the implementation
|
|
888
|
+
const implementationArguments = "implementation" in options &&
|
|
889
|
+
options.implementation != null &&
|
|
890
|
+
options.implementation[CONSTRUCTOR_ARGUMENTS_SYMBOL] != null
|
|
891
|
+
? options.implementation[CONSTRUCTOR_ARGUMENTS_SYMBOL]
|
|
892
|
+
: [];
|
|
893
|
+
this.constructorArguments.set(options.identifier, implementationArguments);
|
|
894
|
+
this.serviceRegistry.set(options.identifier, "implementation" in options && options.implementation != null
|
|
895
|
+
? { ...options, kind }
|
|
896
|
+
: { ...options, kind, newExpression: newExpression });
|
|
897
|
+
}
|
|
898
|
+
/**
|
|
899
|
+
* Returns true if an instance exists that matches the given identifier.
|
|
900
|
+
*/
|
|
901
|
+
hasInstance(identifier) {
|
|
902
|
+
return this.getInstance(identifier) != null;
|
|
903
|
+
}
|
|
904
|
+
/**
|
|
905
|
+
* Gets the cached instance, if any, associated with the given identifier.
|
|
906
|
+
*/
|
|
907
|
+
getInstance(identifier) {
|
|
908
|
+
const instance = this.instances.get(identifier);
|
|
909
|
+
return instance == null ? null : instance;
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Gets an IRegistrationRecord associated with the given identifier.
|
|
913
|
+
*/
|
|
914
|
+
getRegistrationRecord({ identifier, parentChain, }) {
|
|
915
|
+
const record = this.serviceRegistry.get(identifier);
|
|
916
|
+
if (record == null) {
|
|
917
|
+
throw new ReferenceError(`${this.constructor.name} could not find a service for identifier: "${identifier}". ${parentChain == null || parentChain.length < 1
|
|
918
|
+
? ""
|
|
919
|
+
: `It is required by the service: '${parentChain
|
|
920
|
+
.map((parent) => parent.identifier)
|
|
921
|
+
.join(" -> ")}'.`} Remember to register it as a service!`);
|
|
922
|
+
}
|
|
923
|
+
return record;
|
|
924
|
+
}
|
|
925
|
+
/**
|
|
926
|
+
* Caches the given instance so that it can be retrieved in the future.
|
|
927
|
+
*/
|
|
928
|
+
setInstance(identifier, instance) {
|
|
929
|
+
this.instances.set(identifier, instance);
|
|
930
|
+
return instance;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Gets a lazy reference to another service
|
|
934
|
+
*/
|
|
935
|
+
getLazyIdentifier(lazyPointer) {
|
|
936
|
+
return (new Proxy({}, { get: (_, key) => lazyPointer()[key] }));
|
|
937
|
+
}
|
|
938
|
+
/**
|
|
939
|
+
* Constructs a new instance of the given identifier and returns it.
|
|
940
|
+
* It checks the constructor arguments and injects any services it might depend on recursively.
|
|
941
|
+
*/
|
|
942
|
+
constructInstance({ identifier, parentChain = [], }) {
|
|
943
|
+
const registrationRecord = this.getRegistrationRecord({
|
|
944
|
+
identifier,
|
|
945
|
+
parentChain,
|
|
946
|
+
});
|
|
947
|
+
// If an instance already exists (and it is a singleton), return that one
|
|
948
|
+
if (this.hasInstance(identifier) &&
|
|
949
|
+
registrationRecord.kind === "SINGLETON") {
|
|
950
|
+
return this.getInstance(identifier);
|
|
951
|
+
}
|
|
952
|
+
// Otherwise, instantiate a new one
|
|
953
|
+
let instance;
|
|
954
|
+
const me = {
|
|
955
|
+
identifier,
|
|
956
|
+
ref: this.getLazyIdentifier(() => instance),
|
|
957
|
+
};
|
|
958
|
+
// If a user-provided new-expression has been provided, invoke that to get an instance.
|
|
959
|
+
if ("newExpression" in registrationRecord) {
|
|
960
|
+
if (typeof registrationRecord.newExpression !== "function") {
|
|
961
|
+
throw new TypeError(`Could not instantiate the service with the identifier: '${registrationRecord.identifier}': You provided a custom instantiation argument, but it wasn't of type function. It has to be a function that returns whatever should be used as an instance of the Service!`);
|
|
962
|
+
}
|
|
963
|
+
try {
|
|
964
|
+
instance = registrationRecord.newExpression();
|
|
965
|
+
}
|
|
966
|
+
catch (ex) {
|
|
967
|
+
throw new Error(`Could not instantiate the service with the identifier: '${registrationRecord.identifier}': When you registered the service, you provided a custom instantiation function, but it threw an exception when it was run!`);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
else {
|
|
971
|
+
// Find the arguments for the identifier
|
|
972
|
+
const mappedArgs = this.constructorArguments.get(identifier);
|
|
973
|
+
if (mappedArgs == null) {
|
|
974
|
+
throw new ReferenceError(`${this.constructor.name} could not find constructor arguments for the service: '${identifier}'. Have you registered it as a service?`);
|
|
975
|
+
}
|
|
976
|
+
// Instantiate all of the argument services (or re-use them if they were registered as singletons)
|
|
977
|
+
const instanceArgs = mappedArgs.map((dep) => {
|
|
978
|
+
if (dep === undefined)
|
|
979
|
+
return undefined;
|
|
980
|
+
const matchedParent = parentChain.find((parent) => parent.identifier === dep);
|
|
981
|
+
if (matchedParent != null)
|
|
982
|
+
return matchedParent.ref;
|
|
983
|
+
return this.constructInstance({
|
|
984
|
+
identifier: dep,
|
|
985
|
+
parentChain: [...parentChain, me],
|
|
986
|
+
});
|
|
987
|
+
});
|
|
988
|
+
try {
|
|
989
|
+
// Try to construct an instance with 'new' and if it fails, call the implementation directly.
|
|
990
|
+
const newable = registrationRecord.implementation;
|
|
991
|
+
instance = new newable(...instanceArgs);
|
|
992
|
+
}
|
|
993
|
+
catch (ex) {
|
|
994
|
+
if (registrationRecord.implementation == null) {
|
|
995
|
+
throw new ReferenceError(`${this.constructor.name} could not construct a new service of kind: ${identifier}. Reason: No implementation was given!`);
|
|
996
|
+
}
|
|
997
|
+
const constructable = registrationRecord.implementation;
|
|
998
|
+
// Try without 'new' and call the implementation as a function.
|
|
999
|
+
instance = constructable(...instanceArgs);
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
return registrationRecord.kind === "SINGLETON"
|
|
1003
|
+
? this.setInstance(identifier, instance)
|
|
1004
|
+
: instance;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
const DI_COMPILER_ERROR_HINT = `Note: You must use DI-Compiler (https://github.com/wessberg/di-compiler) for this library to work correctly. Please consult the readme for instructions on how to install and configure it for your project.`;
|
|
1008
|
+
|
|
1009
|
+
const container = new DIContainer();
|
|
1010
|
+
|
|
1011
|
+
class WidgetsService {
|
|
1012
|
+
_env;
|
|
1013
|
+
_sdkApi;
|
|
1014
|
+
constructor(_env, _sdkApi) {
|
|
1015
|
+
this._env = _env;
|
|
1016
|
+
this._sdkApi = _sdkApi;
|
|
1017
|
+
}
|
|
1018
|
+
get env() {
|
|
1019
|
+
return this._env;
|
|
1020
|
+
}
|
|
1021
|
+
get sdkApi() {
|
|
1022
|
+
return this._sdkApi;
|
|
1023
|
+
}
|
|
1024
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`Window`, `SDKApi`]; }
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
container.registerSingleton(undefined, { identifier: `WidgetsService`, implementation: WidgetsService });
|
|
1028
|
+
|
|
1029
|
+
// import '../adapters/dateTimeSource/composition';
|
|
1030
|
+
// import '../adapters/uuidGenerator/composition';
|
|
1031
|
+
// import '../effects/eventHandler/composition';
|
|
1032
|
+
// import '../effects/logger/composition';
|
|
1033
|
+
// import '../effects/timer/composition';
|
|
1034
|
+
container.registerSingleton(() => window, { identifier: `Window` });
|
|
1035
|
+
|
|
1036
|
+
class WidgetBase {
|
|
1037
|
+
/**
|
|
1038
|
+
* @see https://github.com/Microsoft/TypeScript/issues/3841#issuecomment-337560146
|
|
1039
|
+
*/
|
|
1040
|
+
["constructor"];
|
|
1041
|
+
static DEFAULTS = {
|
|
1042
|
+
slide: null,
|
|
1043
|
+
activateAfterCreate: false,
|
|
1044
|
+
create: false,
|
|
1045
|
+
localData: {},
|
|
1046
|
+
};
|
|
1047
|
+
static widgetIndex = 0;
|
|
1048
|
+
env = WidgetBase.widgetsService.env;
|
|
1049
|
+
sdkApi = WidgetBase.widgetsService.sdkApi;
|
|
1050
|
+
options = null;
|
|
1051
|
+
element = null;
|
|
1052
|
+
elementId = null;
|
|
1053
|
+
slide = null;
|
|
1054
|
+
slideIndex = null;
|
|
1055
|
+
disableTimer = null;
|
|
1056
|
+
layoutDirection = "ltr";
|
|
1057
|
+
storyId = null;
|
|
1058
|
+
widgetDone = null;
|
|
1059
|
+
showWidgetCompleteToast = null;
|
|
1060
|
+
submitButtonAnimatedView = null;
|
|
1061
|
+
submitButtonView = null;
|
|
1062
|
+
submitButtonViewHeight = 0;
|
|
1063
|
+
savedData = null;
|
|
1064
|
+
localData = null;
|
|
1065
|
+
firstOpenTime = 0;
|
|
1066
|
+
id;
|
|
1067
|
+
constructor(element, options, elementIdGetter, slideGetter) {
|
|
1068
|
+
this.options = extend({}, this.constructor.DEFAULTS, options);
|
|
1069
|
+
this.element = element;
|
|
1070
|
+
if (elementIdGetter) {
|
|
1071
|
+
this.elementId = elementIdGetter(this.element);
|
|
1072
|
+
}
|
|
1073
|
+
else {
|
|
1074
|
+
this.elementId = getValueOrException(getTagData(this.element, "elementId"), "Empty elementId");
|
|
1075
|
+
}
|
|
1076
|
+
if (slideGetter) {
|
|
1077
|
+
this.slide = slideGetter(this.element);
|
|
1078
|
+
}
|
|
1079
|
+
else {
|
|
1080
|
+
this.slide = getValueOrException(this.element.closest(".narrative-slide"), "Empty slide");
|
|
1081
|
+
}
|
|
1082
|
+
this.slideIndex = getValueOrException(getTagDataAsNumber(this.slide, "index"), "Empty slideIndex");
|
|
1083
|
+
this.disableTimer = getTagData(this.slide, "disableTimer") === "1";
|
|
1084
|
+
this.storyId = getValueOrException(getTagDataAsNumber(this.slide, "id"), "Empty storyId");
|
|
1085
|
+
if (this.env.getComputedStyle(this.element).direction === "rtl") {
|
|
1086
|
+
this.layoutDirection = "rtl";
|
|
1087
|
+
}
|
|
1088
|
+
else {
|
|
1089
|
+
this.layoutDirection = "ltr";
|
|
1090
|
+
}
|
|
1091
|
+
this.element.dir = this.layoutDirection;
|
|
1092
|
+
if (this.element.parentElement != null) {
|
|
1093
|
+
this.widgetDone = this.element.parentElement?.nextElementSibling; // geometry + .widget-sent-toast
|
|
1094
|
+
if (this.widgetDone) {
|
|
1095
|
+
if (!this.widgetDone.classList.contains("widget-sent-toast")) {
|
|
1096
|
+
this.widgetDone = null;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
this.showWidgetCompleteToast = Boolean(getValueOrDefault(getTagDataAsNumber(this.element, "showWidgetCompleteToast"), 0));
|
|
1101
|
+
if (!this.showWidgetCompleteToast) {
|
|
1102
|
+
this.widgetDone = null;
|
|
1103
|
+
}
|
|
1104
|
+
if (this.element != null) {
|
|
1105
|
+
this.submitButtonAnimatedView = this.element.querySelector(".submit-button-animated-view");
|
|
1106
|
+
if (this.submitButtonAnimatedView != null) {
|
|
1107
|
+
this.submitButtonView = this.submitButtonAnimatedView.querySelector(".submit-button-view");
|
|
1108
|
+
if (this.submitButtonView != null) {
|
|
1109
|
+
this.submitButtonViewHeight = this.submitButtonView.clientHeight;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
1114
|
+
this.localData = extend({}, this.savedData ?? {}, this.options.localData ?? {});
|
|
1115
|
+
this.id = `w_${this.elementId}_${WidgetBase.widgetIndex}`;
|
|
1116
|
+
++WidgetBase.widgetIndex;
|
|
1117
|
+
}
|
|
1118
|
+
refreshUserData(localData) { }
|
|
1119
|
+
static widgetCacheKey = "ias.story-element";
|
|
1120
|
+
static widgetClassName = "";
|
|
1121
|
+
static getInstance(element) {
|
|
1122
|
+
return data(element, this.widgetCacheKey);
|
|
1123
|
+
}
|
|
1124
|
+
static getInstanceById(id) {
|
|
1125
|
+
const widgetsElements = slice.call(this.widgetsService.env.document.querySelectorAll(`.${this.widgetClassName}`));
|
|
1126
|
+
let widget;
|
|
1127
|
+
forEach(widgetsElements, (element, index) => {
|
|
1128
|
+
const localWidget = data(element, this.widgetCacheKey);
|
|
1129
|
+
if (localWidget && localWidget.id === id) {
|
|
1130
|
+
widget = localWidget;
|
|
1131
|
+
}
|
|
1132
|
+
});
|
|
1133
|
+
return widget;
|
|
1134
|
+
}
|
|
1135
|
+
static createInstance(instantiate, element, options) {
|
|
1136
|
+
// get from objects cache (just Map<key, data> where key assigned to HTMLElement)
|
|
1137
|
+
let instance = WidgetBase.getInstance(element);
|
|
1138
|
+
if (instance == null) {
|
|
1139
|
+
// can throw Error
|
|
1140
|
+
instance = instantiate(element, options);
|
|
1141
|
+
// save object in cache by key associated with HTMLElement
|
|
1142
|
+
data(element, WidgetBase.widgetCacheKey, instance);
|
|
1143
|
+
}
|
|
1144
|
+
return instance;
|
|
1145
|
+
}
|
|
1146
|
+
static initWidgets(instantiate, elements, localData) {
|
|
1147
|
+
if (localData != null) {
|
|
1148
|
+
forEach(elements, element => {
|
|
1149
|
+
this.createInstance(instantiate, element, {
|
|
1150
|
+
slide: null,
|
|
1151
|
+
localData,
|
|
1152
|
+
});
|
|
1153
|
+
});
|
|
1154
|
+
return Promise.resolve(localData);
|
|
1155
|
+
}
|
|
1156
|
+
else {
|
|
1157
|
+
return new Promise(resolve => {
|
|
1158
|
+
this.getLocalData().then(localData => {
|
|
1159
|
+
forEach(elements, element => {
|
|
1160
|
+
this.createInstance(instantiate, element, {
|
|
1161
|
+
slide: null,
|
|
1162
|
+
localData,
|
|
1163
|
+
});
|
|
1164
|
+
});
|
|
1165
|
+
resolve(localData);
|
|
1166
|
+
});
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
static get widgetsService() {
|
|
1171
|
+
return container.get({ identifier: "WidgetsService" });
|
|
1172
|
+
}
|
|
1173
|
+
static getLocalData() {
|
|
1174
|
+
return this.widgetsService.sdkApi.getStoryLocalData();
|
|
1175
|
+
}
|
|
1176
|
+
getLocalData() {
|
|
1177
|
+
return this.constructor.getLocalData();
|
|
1178
|
+
}
|
|
1179
|
+
static setLocalData(keyValue, sendToServer, syncWithRuntimeLocalData) {
|
|
1180
|
+
// push json object as string
|
|
1181
|
+
if (sendToServer === undefined) {
|
|
1182
|
+
sendToServer = true;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
sendToServer = Boolean(sendToServer);
|
|
1186
|
+
}
|
|
1187
|
+
if (syncWithRuntimeLocalData === undefined) {
|
|
1188
|
+
syncWithRuntimeLocalData = true;
|
|
1189
|
+
}
|
|
1190
|
+
else {
|
|
1191
|
+
syncWithRuntimeLocalData = Boolean(syncWithRuntimeLocalData);
|
|
1192
|
+
}
|
|
1193
|
+
if (syncWithRuntimeLocalData) {
|
|
1194
|
+
this.getLocalData().then(localData => {
|
|
1195
|
+
// 1 - old values, 2 - new values
|
|
1196
|
+
keyValue = extend({}, localData, keyValue);
|
|
1197
|
+
// todo make async via promise or async
|
|
1198
|
+
this.widgetsService.sdkApi.setStoryLocalData(keyValue, sendToServer);
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
else {
|
|
1202
|
+
// todo make async via promise or async
|
|
1203
|
+
this.widgetsService.sdkApi.setStoryLocalData(keyValue, sendToServer);
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
setLocalData(keyValue, sendToServer, syncWithRuntimeLocalData) {
|
|
1207
|
+
return this.constructor.setLocalData(keyValue, sendToServer, syncWithRuntimeLocalData);
|
|
1208
|
+
}
|
|
1209
|
+
static sendStatisticEventToApp(name, data, devPayload) {
|
|
1210
|
+
sendStatisticEventToApp(this.widgetsService.sdkApi, name, data, devPayload);
|
|
1211
|
+
}
|
|
1212
|
+
sendStatisticEventToApp(name, data, devPayload) {
|
|
1213
|
+
this.constructor.sendStatisticEventToApp(name, data, devPayload);
|
|
1214
|
+
}
|
|
1215
|
+
showNextSlide() {
|
|
1216
|
+
this.sdkApi.showNextSlide(getSlideDuration(this.sdkApi, this.storyId, this.slideIndex));
|
|
1217
|
+
}
|
|
1218
|
+
_showLayout(layers, selectIndex, withStatEvent = false) {
|
|
1219
|
+
if (this.sdkApi.isExistsShowLayer()) {
|
|
1220
|
+
this.sdkApi.showLayer(selectIndex);
|
|
1221
|
+
}
|
|
1222
|
+
else {
|
|
1223
|
+
forEach(layers, (layer, index) => {
|
|
1224
|
+
if (index === selectIndex) {
|
|
1225
|
+
layer.classList.remove("hidden");
|
|
1226
|
+
this.sdkApi.storyAnimation?.start(layer);
|
|
1227
|
+
}
|
|
1228
|
+
else {
|
|
1229
|
+
layer.classList.add("hidden");
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
}
|
|
1233
|
+
if (withStatEvent) {
|
|
1234
|
+
this._statEventLayoutShow(selectIndex);
|
|
1235
|
+
}
|
|
1236
|
+
}
|
|
1237
|
+
_statEventLayoutShow(layoutIndex) {
|
|
1238
|
+
try {
|
|
1239
|
+
this.sendStatisticEventToApp("layout-show", {
|
|
1240
|
+
i: this.storyId,
|
|
1241
|
+
si: this.slideIndex,
|
|
1242
|
+
li: layoutIndex,
|
|
1243
|
+
}, {
|
|
1244
|
+
story_id: this.storyId,
|
|
1245
|
+
slide_index: this.slideIndex,
|
|
1246
|
+
layout_index: layoutIndex,
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
catch (error) {
|
|
1250
|
+
console.error(error);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
static api = {
|
|
1254
|
+
refreshUserData: function (nodes, localData) {
|
|
1255
|
+
const cb = (el, localData) => {
|
|
1256
|
+
var widgetElement = el.closest(`.${WidgetBase.widgetClassName}`);
|
|
1257
|
+
if (widgetElement) {
|
|
1258
|
+
const widget = WidgetBase.getInstance(widgetElement);
|
|
1259
|
+
if (widget) {
|
|
1260
|
+
widget.refreshUserData(localData);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
if (localData != null) {
|
|
1265
|
+
const elements = slice.call(nodes);
|
|
1266
|
+
forEach(elements, el => cb(el, localData));
|
|
1267
|
+
}
|
|
1268
|
+
else {
|
|
1269
|
+
WidgetBase.getLocalData().then(localData => {
|
|
1270
|
+
const elements = slice.call(nodes);
|
|
1271
|
+
forEach(elements, el => cb(el, localData));
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
},
|
|
1275
|
+
};
|
|
1276
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`, `(element: HTMLElement) => string`, `(element: HTMLElement) => HTMLElement`]; }
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
class WidgetCopy extends WidgetBase {
|
|
1280
|
+
static DEFAULTS = {
|
|
1281
|
+
slide: null,
|
|
1282
|
+
activateAfterCreate: false,
|
|
1283
|
+
create: false,
|
|
1284
|
+
localData: {},
|
|
1285
|
+
};
|
|
1286
|
+
static widgetClassName = "narrative-element-copy";
|
|
1287
|
+
button;
|
|
1288
|
+
clipboardTarget;
|
|
1289
|
+
isPromotionalCode;
|
|
1290
|
+
state;
|
|
1291
|
+
msgNetworkError;
|
|
1292
|
+
msgServiceError;
|
|
1293
|
+
msgNoMoreCodes;
|
|
1294
|
+
msgTryAgain;
|
|
1295
|
+
geometry;
|
|
1296
|
+
resultLayer;
|
|
1297
|
+
resultLayerGeometry;
|
|
1298
|
+
constructor(element, options) {
|
|
1299
|
+
super(element, options);
|
|
1300
|
+
this.button = this.element.querySelector(".narrative-element-text-lines");
|
|
1301
|
+
this.clipboardTarget = getTagData(element, "clipboardTarget");
|
|
1302
|
+
this.isPromotionalCode = getTagData(element, "clipboardType") === "promocode";
|
|
1303
|
+
this.state = null;
|
|
1304
|
+
this.msgNetworkError = getTagData(this.element, "msgNetworkError");
|
|
1305
|
+
this.msgServiceError = getTagData(this.element, "msgServiceError");
|
|
1306
|
+
this.msgNoMoreCodes = getTagData(this.element, "msgNoMoreCodes");
|
|
1307
|
+
this.msgTryAgain = getTagData(this.element, "msgTryAgain");
|
|
1308
|
+
this.geometry = this.element.closest(".narrative-element-geometry");
|
|
1309
|
+
this.resultLayer = this.slide.querySelector(".narrative-element-copy-result-variant");
|
|
1310
|
+
if (this.resultLayer && this.geometry) {
|
|
1311
|
+
this.resultLayerGeometry = this.resultLayer.closest(".narrative-element-geometry");
|
|
1312
|
+
// create align center
|
|
1313
|
+
if (this.resultLayerGeometry) {
|
|
1314
|
+
var baseComputedGeometry = window.getComputedStyle(this.geometry);
|
|
1315
|
+
var resultComputedGeometry = window.getComputedStyle(this.resultLayerGeometry);
|
|
1316
|
+
if (parseFloat(resultComputedGeometry.width) < parseFloat(baseComputedGeometry.width)) {
|
|
1317
|
+
// prevent resultLayer shrinking
|
|
1318
|
+
this.resultLayerGeometry.style.setProperty("width", parseFloat(baseComputedGeometry.width) + "px");
|
|
1319
|
+
resultComputedGeometry = window.getComputedStyle(this.resultLayerGeometry);
|
|
1320
|
+
}
|
|
1321
|
+
var geometryCenter = parseFloat(baseComputedGeometry.left) + parseFloat(baseComputedGeometry.width) / 2;
|
|
1322
|
+
var resultLayerGeometryWidth = parseFloat(resultComputedGeometry.width);
|
|
1323
|
+
var newResultLayerGeometryLeft = geometryCenter - resultLayerGeometryWidth / 2;
|
|
1324
|
+
this.resultLayerGeometry.style.setProperty("left", newResultLayerGeometryLeft + "px");
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
if (this.isPromotionalCode) {
|
|
1328
|
+
this.fetchPromoCode();
|
|
1329
|
+
}
|
|
1330
|
+
// this.refreshUserData(this.options.localData);
|
|
1331
|
+
}
|
|
1332
|
+
refreshUserData(localData) { }
|
|
1333
|
+
isTransparentElement() {
|
|
1334
|
+
if (this.element) {
|
|
1335
|
+
try {
|
|
1336
|
+
var color = window.getComputedStyle(this.element).color;
|
|
1337
|
+
if (color === "transparent" || color === "rgba(0, 0, 0, 0)" || color === "rgba(0,0,0,0)") {
|
|
1338
|
+
return true;
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
catch (err) {
|
|
1342
|
+
console.error(err);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
return false;
|
|
1346
|
+
}
|
|
1347
|
+
changeText(newText) {
|
|
1348
|
+
if (this.button) {
|
|
1349
|
+
this.button.textContent = newText;
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
fetchPromoCode() {
|
|
1353
|
+
this.state = 0;
|
|
1354
|
+
if (this.localData["_cp_g_" + this.elementId + "_pc"] !== undefined) {
|
|
1355
|
+
this.state = 1;
|
|
1356
|
+
this.clipboardTarget = this.localData["_cp_g_" + this.elementId + "_pc"];
|
|
1357
|
+
if (this.clipboardTarget != null) {
|
|
1358
|
+
this.changeText(this.clipboardTarget);
|
|
1359
|
+
}
|
|
1360
|
+
removeClass(this.element, "loader");
|
|
1361
|
+
}
|
|
1362
|
+
if (this.state === 0) {
|
|
1363
|
+
if (!this.isTransparentElement()) {
|
|
1364
|
+
// for transparent element
|
|
1365
|
+
addClass(this.element, "loader");
|
|
1366
|
+
}
|
|
1367
|
+
// fetch promo code
|
|
1368
|
+
var path = "story/" + this.storyId + "/widget/" + this.elementId + "/promo-code/" + this.clipboardTarget;
|
|
1369
|
+
var headers = {
|
|
1370
|
+
accept: "application/json",
|
|
1371
|
+
"Content-Type": "application/json",
|
|
1372
|
+
};
|
|
1373
|
+
var profileKey = "fetch-promo-code";
|
|
1374
|
+
Promise.all([
|
|
1375
|
+
this.sdkApi.sendApiRequest(path, "POST", null, headers, null, profileKey),
|
|
1376
|
+
new Promise(function (t, e) {
|
|
1377
|
+
return setTimeout(t, 300);
|
|
1378
|
+
}),
|
|
1379
|
+
]).then(values => {
|
|
1380
|
+
var r = values[0];
|
|
1381
|
+
var status = r.status;
|
|
1382
|
+
var code = null;
|
|
1383
|
+
var success = false;
|
|
1384
|
+
if (status === 200 || status === 201) {
|
|
1385
|
+
if (r.data)
|
|
1386
|
+
code = r.data.code;
|
|
1387
|
+
if (code) {
|
|
1388
|
+
// success case
|
|
1389
|
+
this.clipboardTarget = code;
|
|
1390
|
+
this.changeText(this.clipboardTarget);
|
|
1391
|
+
success = true;
|
|
1392
|
+
this.state = 1;
|
|
1393
|
+
removeClass(this.element, "loader");
|
|
1394
|
+
if (status === 201) {
|
|
1395
|
+
this.localData["_cp_g_" + this.elementId + "_pc_fetched_at"] = Math.round(new Date().getTime() / 1000);
|
|
1396
|
+
this.localData["_&ts_cp_g_" + this.elementId + "_pc_fetched_at"] = Math.round(new Date().getTime() / 1000);
|
|
1397
|
+
}
|
|
1398
|
+
this.localData["_cp_g_" + this.elementId + "_pc"] = code;
|
|
1399
|
+
this.setLocalData(this.localData, true);
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
this.msgNoMoreCodes && this.sdkApi.showToast(this.msgNoMoreCodes);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
else if (status === 12163 || status === 12002) {
|
|
1406
|
+
this.msgNetworkError && this.sdkApi.showToast(this.msgNetworkError);
|
|
1407
|
+
}
|
|
1408
|
+
else {
|
|
1409
|
+
this.msgServiceError && this.sdkApi.showToast(this.msgServiceError);
|
|
1410
|
+
}
|
|
1411
|
+
if (!success) {
|
|
1412
|
+
this.state = 3;
|
|
1413
|
+
this.changeText(this.msgTryAgain ?? "");
|
|
1414
|
+
removeClass(this.element, "loader");
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
getStateValue() {
|
|
1420
|
+
return this.state;
|
|
1421
|
+
}
|
|
1422
|
+
getIsPromotionalCode() {
|
|
1423
|
+
return this.isPromotionalCode;
|
|
1424
|
+
}
|
|
1425
|
+
_statEventCopyClick(clipboardTarget) {
|
|
1426
|
+
try {
|
|
1427
|
+
var buttonText = this.button?.textContent ?? "";
|
|
1428
|
+
this.sendStatisticEventToApp("w-copy", {
|
|
1429
|
+
i: this.storyId,
|
|
1430
|
+
si: this.slideIndex,
|
|
1431
|
+
wi: this.elementId,
|
|
1432
|
+
wl: buttonText,
|
|
1433
|
+
wt: clipboardTarget,
|
|
1434
|
+
}, {
|
|
1435
|
+
story_id: this.storyId,
|
|
1436
|
+
slide_index: this.slideIndex,
|
|
1437
|
+
widget_id: this.elementId,
|
|
1438
|
+
widget_label: buttonText,
|
|
1439
|
+
widget_value: clipboardTarget,
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
catch (error) {
|
|
1443
|
+
console.error(error);
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
_select() {
|
|
1447
|
+
this.element.classList.add("done");
|
|
1448
|
+
if (this.resultLayer) {
|
|
1449
|
+
this.resultLayer.classList.add("done");
|
|
1450
|
+
}
|
|
1451
|
+
if (this.disableTimer) {
|
|
1452
|
+
// флаг - что таймер уже стартанул (в layout или добавить объект sharedMemory)
|
|
1453
|
+
// смотрим что прозрачный текст - тогда и лоадер прозрачный
|
|
1454
|
+
// _log("_showNarrativeNextSlide: " + getSlideDuration(this.narrativeId, this.slideIndex), true);
|
|
1455
|
+
this.showNextSlide();
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
copyToClipboard(element) {
|
|
1459
|
+
this._select();
|
|
1460
|
+
var text = this.clipboardTarget ?? "";
|
|
1461
|
+
Clipboard.copy(text);
|
|
1462
|
+
this.completeWidget();
|
|
1463
|
+
this._statEventCopyClick(text);
|
|
1464
|
+
}
|
|
1465
|
+
completeWidget() {
|
|
1466
|
+
this.localData["_cp_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
1467
|
+
// ответ на вопрос
|
|
1468
|
+
this.localData["_&ts_cp_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
1469
|
+
this.setLocalData(this.localData, true);
|
|
1470
|
+
}
|
|
1471
|
+
isDone() {
|
|
1472
|
+
return this.localData["_cp_g_" + this.elementId + "_done_at"] !== undefined;
|
|
1473
|
+
}
|
|
1474
|
+
static api = {
|
|
1475
|
+
...WidgetBase.api,
|
|
1476
|
+
initWidget: function (nodeList, localData) {
|
|
1477
|
+
// prevent initWidget for result layer
|
|
1478
|
+
const elements = slice.call(nodeList).filter(element => !element.classList.contains("narrative-element-copy-result-variant"));
|
|
1479
|
+
WidgetCopy.initWidgets((element, options) => new WidgetCopy(element, options), elements, localData);
|
|
1480
|
+
},
|
|
1481
|
+
click: function (element) {
|
|
1482
|
+
const widgetElement = element.closest(`.${WidgetCopy.widgetClassName}`);
|
|
1483
|
+
if (widgetElement) {
|
|
1484
|
+
const widget = WidgetCopy.getInstance(widgetElement);
|
|
1485
|
+
if (widget) {
|
|
1486
|
+
if (!widget.getIsPromotionalCode()) {
|
|
1487
|
+
widget.copyToClipboard(element);
|
|
1488
|
+
}
|
|
1489
|
+
else if (widget.getStateValue() === 1) {
|
|
1490
|
+
widget.copyToClipboard(element);
|
|
1491
|
+
}
|
|
1492
|
+
else if (widget.getStateValue() === 3) {
|
|
1493
|
+
widget.fetchPromoCode();
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
return false;
|
|
1498
|
+
},
|
|
1499
|
+
};
|
|
1500
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
1501
|
+
}
|
|
1502
|
+
|
|
1503
|
+
/** QUIZ */
|
|
1504
|
+
class WidgetDataInput extends WidgetBase {
|
|
1505
|
+
static DEFAULTS = {
|
|
1506
|
+
slide: null,
|
|
1507
|
+
activateAfterCreate: false,
|
|
1508
|
+
create: false,
|
|
1509
|
+
localData: {},
|
|
1510
|
+
};
|
|
1511
|
+
static widgetClassName = "narrative-element-data-input";
|
|
1512
|
+
label;
|
|
1513
|
+
elementRect;
|
|
1514
|
+
inputElement;
|
|
1515
|
+
textElement;
|
|
1516
|
+
inputPlaceholderValue;
|
|
1517
|
+
/**
|
|
1518
|
+
* @throws Error
|
|
1519
|
+
* @param element
|
|
1520
|
+
* @param options
|
|
1521
|
+
*/
|
|
1522
|
+
constructor(element, options) {
|
|
1523
|
+
super(element, options);
|
|
1524
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
1525
|
+
this.elementRect = this.element.getBoundingClientRect();
|
|
1526
|
+
this.inputElement = getValueOrException(this.element.querySelector(".input-view .input"), "Empty .input-view .input");
|
|
1527
|
+
this.textElement = getValueOrException(this.inputElement.querySelector(".narrative-element-text-lines"), "Empty .narrative-element-text-lines");
|
|
1528
|
+
this.inputPlaceholderValue = this.textElement.innerHTML;
|
|
1529
|
+
this.refreshUserData(this.options.localData);
|
|
1530
|
+
}
|
|
1531
|
+
refreshUserData(localData) {
|
|
1532
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
1533
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
1534
|
+
var text = this.localData["_di_g_" + this.elementId + "_t"];
|
|
1535
|
+
this._fillUserText(text);
|
|
1536
|
+
if (text) {
|
|
1537
|
+
this.element.classList.add("done");
|
|
1538
|
+
if (this.disableTimer) {
|
|
1539
|
+
this.showNextSlide();
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
_statEventFocusIn() {
|
|
1544
|
+
try {
|
|
1545
|
+
var labelText = this.label ? this.label.textContent ?? "" : "";
|
|
1546
|
+
WidgetBase.sendStatisticEventToApp("w-data-input-focus", {
|
|
1547
|
+
i: this.storyId,
|
|
1548
|
+
si: this.slideIndex,
|
|
1549
|
+
wi: this.elementId,
|
|
1550
|
+
wl: labelText,
|
|
1551
|
+
}, {
|
|
1552
|
+
story_id: this.storyId,
|
|
1553
|
+
slide_index: this.slideIndex,
|
|
1554
|
+
widget_id: this.elementId,
|
|
1555
|
+
widget_label: labelText,
|
|
1556
|
+
});
|
|
1557
|
+
}
|
|
1558
|
+
catch (error) {
|
|
1559
|
+
console.error(error);
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
_statEventInputSave(answerText) {
|
|
1563
|
+
try {
|
|
1564
|
+
const labelText = this.label ? this.label.textContent ?? "" : "";
|
|
1565
|
+
WidgetBase.sendStatisticEventToApp("w-data-input-save", {
|
|
1566
|
+
i: this.storyId,
|
|
1567
|
+
si: this.slideIndex,
|
|
1568
|
+
wi: this.elementId,
|
|
1569
|
+
wl: labelText,
|
|
1570
|
+
wv: answerText,
|
|
1571
|
+
}, {
|
|
1572
|
+
story_id: this.storyId,
|
|
1573
|
+
slide_index: this.slideIndex,
|
|
1574
|
+
widget_id: this.elementId,
|
|
1575
|
+
widget_label: labelText,
|
|
1576
|
+
widget_value: answerText,
|
|
1577
|
+
});
|
|
1578
|
+
}
|
|
1579
|
+
catch (error) {
|
|
1580
|
+
console.error(error);
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
isDone() {
|
|
1584
|
+
return Boolean(this.localData["_di_g_" + this.elementId + "_t"]);
|
|
1585
|
+
}
|
|
1586
|
+
click(element) {
|
|
1587
|
+
if (this.isDone()) {
|
|
1588
|
+
return true;
|
|
1589
|
+
}
|
|
1590
|
+
this.elementRect = this.element.getBoundingClientRect();
|
|
1591
|
+
if (this.sdkApi.isAndroid || this.sdkApi.isWeb) {
|
|
1592
|
+
this.slide.classList.add("blured");
|
|
1593
|
+
}
|
|
1594
|
+
this.slide.classList.add("data-input-editing");
|
|
1595
|
+
const dataString = this.element.dataset["clientdialogwidgetconfig"];
|
|
1596
|
+
if (this.sdkApi.isExistsShowStoryTextInput && dataString) {
|
|
1597
|
+
const data = JSON.parse(dataString);
|
|
1598
|
+
data.size = getElementBounding(this.env, this.elementRect);
|
|
1599
|
+
if (!this.disableTimer) {
|
|
1600
|
+
this.sdkApi.pauseUI();
|
|
1601
|
+
}
|
|
1602
|
+
try {
|
|
1603
|
+
data.text.value = data.text.value.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
1604
|
+
data.input.text.placeholder = data.input.text.placeholder.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
1605
|
+
data.configV2.main.question.text.value = data.configV2.main.question.text.value
|
|
1606
|
+
.replaceAll("\\n", "\n")
|
|
1607
|
+
.replaceAll("\\r", "\r")
|
|
1608
|
+
.replaceAll("\\t", "\t");
|
|
1609
|
+
data.configV2.main.input.text.placeholder = data.configV2.main.input.text.placeholder
|
|
1610
|
+
.replaceAll("\\n", "\n")
|
|
1611
|
+
.replaceAll("\\r", "\r")
|
|
1612
|
+
.replaceAll("\\t", "\t");
|
|
1613
|
+
}
|
|
1614
|
+
catch (e) {
|
|
1615
|
+
console.error(e);
|
|
1616
|
+
}
|
|
1617
|
+
this.sdkApi.showStoryTextInput(this.id, data);
|
|
1618
|
+
this._statEventFocusIn();
|
|
1619
|
+
}
|
|
1620
|
+
return false;
|
|
1621
|
+
}
|
|
1622
|
+
_fillUserText(text) {
|
|
1623
|
+
if (this.inputElement && this.textElement) {
|
|
1624
|
+
if (text) {
|
|
1625
|
+
this.inputElement.classList.remove("_is-placeholder");
|
|
1626
|
+
text = text.replace(new RegExp("\r?\n", "g"), "<br />");
|
|
1627
|
+
this.textElement.innerHTML = text;
|
|
1628
|
+
}
|
|
1629
|
+
else {
|
|
1630
|
+
this.inputElement.classList.add("_is-placeholder");
|
|
1631
|
+
this.textElement.innerHTML = this.inputPlaceholderValue;
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
setUserText(text) {
|
|
1636
|
+
this.slide.classList.remove("data-input-editing");
|
|
1637
|
+
this.slide.classList.remove("blured");
|
|
1638
|
+
var needResumeUITimer = true;
|
|
1639
|
+
if (text) {
|
|
1640
|
+
this._fillUserText(text);
|
|
1641
|
+
this.localData["_di_g_" + this.elementId + "_t"] = text;
|
|
1642
|
+
// answer to question
|
|
1643
|
+
this.localData["_&ts_di_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
1644
|
+
if (this.widgetDone) {
|
|
1645
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
1646
|
+
setTimeout(() => {
|
|
1647
|
+
this.widgetDone?.classList.remove("active");
|
|
1648
|
+
setTimeout(() => {
|
|
1649
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
1650
|
+
}, 250);
|
|
1651
|
+
}, 2000);
|
|
1652
|
+
}
|
|
1653
|
+
this.setLocalData(this.localData, true);
|
|
1654
|
+
this._statEventInputSave(text);
|
|
1655
|
+
if (this.disableTimer) {
|
|
1656
|
+
if ("_showNarrativeNextSlide" in window) {
|
|
1657
|
+
this.showNextSlide();
|
|
1658
|
+
needResumeUITimer = false;
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
if (needResumeUITimer && !this.disableTimer) {
|
|
1663
|
+
this.sdkApi.resumeUI();
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
static api = {
|
|
1667
|
+
...WidgetBase.api,
|
|
1668
|
+
initWidget: function (nodeList, localData) {
|
|
1669
|
+
WidgetDataInput.initWidgets((element, options) => new WidgetDataInput(element, options), slice.call(nodeList), localData);
|
|
1670
|
+
},
|
|
1671
|
+
click: function (element) {
|
|
1672
|
+
const widgetElement = element.closest(`.${WidgetDataInput.widgetClassName}`);
|
|
1673
|
+
if (widgetElement) {
|
|
1674
|
+
const widget = WidgetDataInput.getInstance(widgetElement);
|
|
1675
|
+
if (widget) {
|
|
1676
|
+
return widget.click(element);
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
return true;
|
|
1680
|
+
},
|
|
1681
|
+
setUserData: function (id, text) {
|
|
1682
|
+
WidgetDataInput.getInstanceById(id)?.setUserText(text);
|
|
1683
|
+
},
|
|
1684
|
+
};
|
|
1685
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
class WidgetDateCountdown extends WidgetBase {
|
|
1689
|
+
static DEFAULTS = {
|
|
1690
|
+
slide: null,
|
|
1691
|
+
activateAfterCreate: false,
|
|
1692
|
+
create: false,
|
|
1693
|
+
localData: {},
|
|
1694
|
+
layers: [],
|
|
1695
|
+
};
|
|
1696
|
+
static widgetClassName = "narrative-element-date-countdown";
|
|
1697
|
+
label;
|
|
1698
|
+
layers;
|
|
1699
|
+
messages;
|
|
1700
|
+
timestampSeconds;
|
|
1701
|
+
diff;
|
|
1702
|
+
timerInited;
|
|
1703
|
+
pendingUpdate;
|
|
1704
|
+
firstGroup1;
|
|
1705
|
+
firstGroup2;
|
|
1706
|
+
firstGroupCaption;
|
|
1707
|
+
secondGroup1;
|
|
1708
|
+
secondGroup2;
|
|
1709
|
+
secondGroupCaption;
|
|
1710
|
+
thirdGroup1;
|
|
1711
|
+
thirdGroup2;
|
|
1712
|
+
thirdGroupCaption;
|
|
1713
|
+
constructor(element, options) {
|
|
1714
|
+
super(element, options);
|
|
1715
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
1716
|
+
this.messages = {
|
|
1717
|
+
days: getTagData(this.element, "tDays") ?? "",
|
|
1718
|
+
hours: getTagData(this.element, "tHours") ?? "",
|
|
1719
|
+
minutes: getTagData(this.element, "tMinutes") ?? "",
|
|
1720
|
+
seconds: getTagData(this.element, "tSeconds") ?? "",
|
|
1721
|
+
};
|
|
1722
|
+
this.timestampSeconds = getValueOrException(getTagDataAsNumber(this.element, "timestampSeconds"), "Empty timestampSeconds");
|
|
1723
|
+
this.diff = 0;
|
|
1724
|
+
this.timerInited = false;
|
|
1725
|
+
this.pendingUpdate = true;
|
|
1726
|
+
this.layers = this.options.layers;
|
|
1727
|
+
// if (false) {
|
|
1728
|
+
// // if (sendApiRequestSupported()) {
|
|
1729
|
+
// // fetch project time
|
|
1730
|
+
// var path = "story/" + this.storyId + "/widget/" + this.elementId + "/timestamp";
|
|
1731
|
+
// var profileKey = "fetch-story-timestamp";
|
|
1732
|
+
// this.sdkApi
|
|
1733
|
+
// .sendApiRequest<{ timestamp: number }>(path, "GET", null, null, null, profileKey)
|
|
1734
|
+
// .then(response => {
|
|
1735
|
+
// var status = response.status;
|
|
1736
|
+
// var timestamp = null;
|
|
1737
|
+
// if (status === 200) {
|
|
1738
|
+
// if (response.data) timestamp = response.data.timestamp;
|
|
1739
|
+
// if (timestamp) {
|
|
1740
|
+
// this.diff = new Date().getTime() - timestamp * 1000;
|
|
1741
|
+
// }
|
|
1742
|
+
// }
|
|
1743
|
+
//
|
|
1744
|
+
// this.initTimer();
|
|
1745
|
+
// })
|
|
1746
|
+
// .catch( (reason)=> {
|
|
1747
|
+
// console.error(reason);
|
|
1748
|
+
// this.initTimer();
|
|
1749
|
+
// });
|
|
1750
|
+
// } else {
|
|
1751
|
+
this.initTimer();
|
|
1752
|
+
// }
|
|
1753
|
+
// this.refreshUserData(this.options.localData);
|
|
1754
|
+
}
|
|
1755
|
+
refreshUserData(localData) { }
|
|
1756
|
+
pause() {
|
|
1757
|
+
if (this.timerInited) {
|
|
1758
|
+
this.pendingUpdate = false;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
resume() {
|
|
1762
|
+
if (this.timerInited) {
|
|
1763
|
+
this.pendingUpdate = true;
|
|
1764
|
+
this.updateTimer();
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
initTimer() {
|
|
1768
|
+
// find groups
|
|
1769
|
+
this.firstGroup1 = getValueOrException(this.element.querySelector(".date-item-view-group-1 .date-output-label-1"), "Empty firstGroup1");
|
|
1770
|
+
this.firstGroup2 = getValueOrException(this.element.querySelector(".date-item-view-group-1 .date-output-label-2"), "Empty firstGroup2");
|
|
1771
|
+
this.firstGroupCaption = getValueOrException(this.element.querySelector(".date-item-view-group-1 .date-item-caption"), "Empty firstGroupCaption");
|
|
1772
|
+
this.secondGroup1 = getValueOrException(this.element.querySelector(".date-item-view-group-2 .date-output-label-1"), "Empty secondGroup1");
|
|
1773
|
+
this.secondGroup2 = getValueOrException(this.element.querySelector(".date-item-view-group-2 .date-output-label-2"), "Empty secondGroup2");
|
|
1774
|
+
this.secondGroupCaption = getValueOrException(this.element.querySelector(".date-item-view-group-2 .date-item-caption"), "Empty secondGroupCaption");
|
|
1775
|
+
this.thirdGroup1 = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-output-label-1"), "Empty thirdGroup1");
|
|
1776
|
+
this.thirdGroup2 = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-output-label-2"), "Empty thirdGroup2");
|
|
1777
|
+
this.thirdGroupCaption = getValueOrException(this.element.querySelector(".date-item-view-group-3 .date-item-caption"), "Empty thirdGroupCaption");
|
|
1778
|
+
this.timestampSeconds *= 1000;
|
|
1779
|
+
this.timerInited = true;
|
|
1780
|
+
var value = this.timestampSeconds - (new Date().getTime() - this.diff);
|
|
1781
|
+
if (value > 0) {
|
|
1782
|
+
this._showLayout(this.layers, 0);
|
|
1783
|
+
}
|
|
1784
|
+
this.updateTimer();
|
|
1785
|
+
}
|
|
1786
|
+
updateTimer() {
|
|
1787
|
+
var value = this.timestampSeconds - (new Date().getTime() - this.diff);
|
|
1788
|
+
if (value > 0) {
|
|
1789
|
+
var result = this._asDuration(Math.round(value / 1000));
|
|
1790
|
+
if (result.days) {
|
|
1791
|
+
this.firstGroupCaption.textContent = this.messages.days;
|
|
1792
|
+
this.firstGroup1.textContent = result.day1;
|
|
1793
|
+
this.firstGroup2.textContent = result.day2;
|
|
1794
|
+
this.secondGroupCaption.textContent = this.messages.hours;
|
|
1795
|
+
this.secondGroup1.textContent = result.hour1;
|
|
1796
|
+
this.secondGroup2.textContent = result.hour2;
|
|
1797
|
+
this.thirdGroupCaption.textContent = this.messages.minutes;
|
|
1798
|
+
this.thirdGroup1.textContent = result.minute1;
|
|
1799
|
+
this.thirdGroup2.textContent = result.minute2;
|
|
1800
|
+
}
|
|
1801
|
+
else {
|
|
1802
|
+
this.firstGroupCaption.textContent = this.messages.hours;
|
|
1803
|
+
this.firstGroup1.textContent = result.hour1;
|
|
1804
|
+
this.firstGroup2.textContent = result.hour2;
|
|
1805
|
+
this.secondGroupCaption.textContent = this.messages.minutes;
|
|
1806
|
+
this.secondGroup1.textContent = result.minute1;
|
|
1807
|
+
this.secondGroup2.textContent = result.minute2;
|
|
1808
|
+
this.thirdGroupCaption.textContent = this.messages.seconds;
|
|
1809
|
+
this.thirdGroup1.textContent = result.second1;
|
|
1810
|
+
this.thirdGroup2.textContent = result.second2;
|
|
1811
|
+
}
|
|
1812
|
+
// this.pendingUpdate = true;
|
|
1813
|
+
}
|
|
1814
|
+
else {
|
|
1815
|
+
this.pendingUpdate = false;
|
|
1816
|
+
this._showLayout(this.layers, 1);
|
|
1817
|
+
}
|
|
1818
|
+
if (this.pendingUpdate) {
|
|
1819
|
+
this.env.requestAnimationFrame(() => this.updateTimer());
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
_asDuration(value) {
|
|
1823
|
+
var result = {
|
|
1824
|
+
days: false,
|
|
1825
|
+
day1: "0",
|
|
1826
|
+
day2: "0",
|
|
1827
|
+
hour1: "0",
|
|
1828
|
+
hour2: "0",
|
|
1829
|
+
minute1: "0",
|
|
1830
|
+
minute2: "0",
|
|
1831
|
+
second1: "0",
|
|
1832
|
+
second2: "0",
|
|
1833
|
+
};
|
|
1834
|
+
if (value === undefined || value === null) {
|
|
1835
|
+
return result;
|
|
1836
|
+
}
|
|
1837
|
+
if (value < 0) {
|
|
1838
|
+
return result;
|
|
1839
|
+
}
|
|
1840
|
+
value = Math.floor(value);
|
|
1841
|
+
var days = Math.floor((value / 86400) % 365);
|
|
1842
|
+
var hours = Math.floor((value / 3600) % 24);
|
|
1843
|
+
var minutes = Math.floor((value / 60) % 60);
|
|
1844
|
+
var seconds = value % 60;
|
|
1845
|
+
var pair;
|
|
1846
|
+
if (days > 0) {
|
|
1847
|
+
result.days = true;
|
|
1848
|
+
if (days < 10)
|
|
1849
|
+
result.day2 = String(days);
|
|
1850
|
+
else {
|
|
1851
|
+
pair = String(days).split("");
|
|
1852
|
+
result.day1 = pair[0];
|
|
1853
|
+
result.day2 = pair[1];
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
if (hours < 10)
|
|
1857
|
+
result.hour2 = String(hours);
|
|
1858
|
+
else {
|
|
1859
|
+
pair = String(hours).split("");
|
|
1860
|
+
result.hour1 = pair[0];
|
|
1861
|
+
result.hour2 = pair[1];
|
|
1862
|
+
}
|
|
1863
|
+
if (minutes < 10)
|
|
1864
|
+
result.minute2 = String(minutes);
|
|
1865
|
+
else {
|
|
1866
|
+
pair = String(minutes).split("");
|
|
1867
|
+
result.minute1 = pair[0];
|
|
1868
|
+
result.minute2 = pair[1];
|
|
1869
|
+
}
|
|
1870
|
+
if (seconds < 10)
|
|
1871
|
+
result.second2 = String(seconds);
|
|
1872
|
+
else {
|
|
1873
|
+
pair = String(seconds).split("");
|
|
1874
|
+
result.second1 = pair[0];
|
|
1875
|
+
result.second2 = pair[1];
|
|
1876
|
+
}
|
|
1877
|
+
return result;
|
|
1878
|
+
}
|
|
1879
|
+
static api = {
|
|
1880
|
+
...WidgetBase.api,
|
|
1881
|
+
initWidget: function (nodeList, layers, localData) {
|
|
1882
|
+
WidgetDateCountdown.initWidgets((element, options) => new WidgetDateCountdown(element, { ...options, layers }), slice.call(nodeList), localData);
|
|
1883
|
+
},
|
|
1884
|
+
pause: function (nodeList) {
|
|
1885
|
+
forEach(slice.call(nodeList), function (el, index) {
|
|
1886
|
+
WidgetDateCountdown.getInstance(el)?.pause();
|
|
1887
|
+
});
|
|
1888
|
+
},
|
|
1889
|
+
resume: function (nodeList) {
|
|
1890
|
+
forEach(slice.call(nodeList), function (el, index) {
|
|
1891
|
+
WidgetDateCountdown.getInstance(el)?.resume();
|
|
1892
|
+
});
|
|
1893
|
+
},
|
|
1894
|
+
};
|
|
1895
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
const displaySlide = function (slides, localData) {
|
|
1899
|
+
const multiSlideItem = slides[0];
|
|
1900
|
+
let storyId = undefined;
|
|
1901
|
+
let slideIndex = undefined;
|
|
1902
|
+
if (multiSlideItem != null) {
|
|
1903
|
+
storyId = getTagDataAsNumber(multiSlideItem, "id");
|
|
1904
|
+
slideIndex = getTagDataAsNumber(multiSlideItem, "index");
|
|
1905
|
+
if (multiSlideItem.querySelectorAll(".narrative-element-share[data-with-layer='1'], .narrative-element-poll-layers, .narrative-element-date-countdown, .narrative-element-game").length > 0) {
|
|
1906
|
+
// skip if exists share/poll_layers
|
|
1907
|
+
return;
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
// score
|
|
1911
|
+
var score = null;
|
|
1912
|
+
var selectedIndex = undefined;
|
|
1913
|
+
if (localData["q_score"] !== undefined) {
|
|
1914
|
+
score = parseInt(localData["q_score"]);
|
|
1915
|
+
}
|
|
1916
|
+
else if (localData["t_score"] !== undefined) {
|
|
1917
|
+
score = parseInt(localData["t_score"]);
|
|
1918
|
+
}
|
|
1919
|
+
else if (localData["qg_score"] !== undefined) {
|
|
1920
|
+
score = localData["qg_score"]; // array
|
|
1921
|
+
var tmpScore = score;
|
|
1922
|
+
if (isObject(score)) {
|
|
1923
|
+
tmpScore = Object.values(score);
|
|
1924
|
+
}
|
|
1925
|
+
tmpScore.sort();
|
|
1926
|
+
tmpScore.reverse();
|
|
1927
|
+
if (tmpScore[0] === tmpScore[1]) {
|
|
1928
|
+
forEach(slides, function (slide, index) {
|
|
1929
|
+
var minScore = getTagData(slide, "layerMinScore");
|
|
1930
|
+
if (minScore !== undefined) {
|
|
1931
|
+
if (minScore === "uncertain") {
|
|
1932
|
+
selectedIndex = index;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
else {
|
|
1938
|
+
var maxCategoryCnt = 0;
|
|
1939
|
+
// find quiz category (selectedCategoryIndex) - chosen most often
|
|
1940
|
+
var selectedCategoryIndex = undefined;
|
|
1941
|
+
forEach(score, function (value, i) {
|
|
1942
|
+
var item = parseInt(value);
|
|
1943
|
+
if (item > maxCategoryCnt) {
|
|
1944
|
+
maxCategoryCnt = item;
|
|
1945
|
+
selectedCategoryIndex = parseInt(i);
|
|
1946
|
+
}
|
|
1947
|
+
});
|
|
1948
|
+
// chose slide with correct result
|
|
1949
|
+
forEach(slides, function (slide, index) {
|
|
1950
|
+
var minScore = getTagData(slide, "layerMinScore");
|
|
1951
|
+
if (minScore !== undefined && isNumeric(minScore) && parseInt(minScore) === selectedCategoryIndex) {
|
|
1952
|
+
selectedIndex = index;
|
|
1953
|
+
}
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1957
|
+
if (score === null) {
|
|
1958
|
+
if (slides.length > 0) {
|
|
1959
|
+
var slide = slides[0];
|
|
1960
|
+
slide.classList.remove("hidden");
|
|
1961
|
+
WidgetBase.widgetsService.sdkApi.storyAnimation?.start(slide);
|
|
1962
|
+
return;
|
|
1963
|
+
}
|
|
1964
|
+
score = 0;
|
|
1965
|
+
}
|
|
1966
|
+
if (selectedIndex === undefined) {
|
|
1967
|
+
var map = [];
|
|
1968
|
+
forEach(slides, function (slide, index) {
|
|
1969
|
+
var minScore = getTagData(slide, "layerMinScore");
|
|
1970
|
+
if (minScore !== undefined) {
|
|
1971
|
+
map.push([index, parseInt(minScore)]);
|
|
1972
|
+
}
|
|
1973
|
+
});
|
|
1974
|
+
map.sort(function (a, b) {
|
|
1975
|
+
return a[1] - b[1];
|
|
1976
|
+
});
|
|
1977
|
+
for (var i = map.length - 1; i >= 0; i--) {
|
|
1978
|
+
if (score >= map[i][1]) {
|
|
1979
|
+
selectedIndex = map[i][0];
|
|
1980
|
+
break;
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
}
|
|
1984
|
+
var undefinedResult = true;
|
|
1985
|
+
if (selectedIndex !== undefined) {
|
|
1986
|
+
forEach(slides, function (slide, index) {
|
|
1987
|
+
if (index === selectedIndex) {
|
|
1988
|
+
slide.classList.remove("hidden");
|
|
1989
|
+
undefinedResult = false;
|
|
1990
|
+
WidgetBase.widgetsService.sdkApi.storyAnimation?.start(slide);
|
|
1991
|
+
_sendStatEvent(storyId, slideIndex, selectedIndex);
|
|
1992
|
+
}
|
|
1993
|
+
});
|
|
1994
|
+
}
|
|
1995
|
+
if (undefinedResult) {
|
|
1996
|
+
console.warn("undefinedResult layer index");
|
|
1997
|
+
WidgetBase.widgetsService.sdkApi.showLayer(0);
|
|
1998
|
+
}
|
|
1999
|
+
};
|
|
2000
|
+
const _sendStatEvent = function (storyId, slideIndex, layerIndex) {
|
|
2001
|
+
try {
|
|
2002
|
+
WidgetBase.sendStatisticEventToApp("layout-show", {
|
|
2003
|
+
i: storyId,
|
|
2004
|
+
si: slideIndex,
|
|
2005
|
+
li: layerIndex,
|
|
2006
|
+
});
|
|
2007
|
+
}
|
|
2008
|
+
catch (error) {
|
|
2009
|
+
console.error(error);
|
|
2010
|
+
}
|
|
2011
|
+
};
|
|
2012
|
+
class WidgetMultiSlide {
|
|
2013
|
+
static api = {
|
|
2014
|
+
init: function (slides, localData) {
|
|
2015
|
+
if (localData != null) {
|
|
2016
|
+
displaySlide(slides, localData);
|
|
2017
|
+
}
|
|
2018
|
+
else {
|
|
2019
|
+
WidgetBase.getLocalData().then(function (localData) {
|
|
2020
|
+
displaySlide(slides, localData);
|
|
2021
|
+
});
|
|
2022
|
+
}
|
|
2023
|
+
},
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
class WidgetPoll extends WidgetBase {
|
|
2028
|
+
static DEFAULTS = {
|
|
2029
|
+
slide: null,
|
|
2030
|
+
activateAfterCreate: false,
|
|
2031
|
+
create: false,
|
|
2032
|
+
localData: {},
|
|
2033
|
+
};
|
|
2034
|
+
static widgetClassName = "narrative-element-poll";
|
|
2035
|
+
elementRect;
|
|
2036
|
+
label;
|
|
2037
|
+
percentFillMask;
|
|
2038
|
+
maskedVariants;
|
|
2039
|
+
variantsViewGroup;
|
|
2040
|
+
variants;
|
|
2041
|
+
variantsTexts;
|
|
2042
|
+
isInvertedPercentFilledMaskDirection;
|
|
2043
|
+
getUseResponseOnFirstButton;
|
|
2044
|
+
getUseResponseOnSecondButton;
|
|
2045
|
+
showClientTotalResult;
|
|
2046
|
+
selectedVariant;
|
|
2047
|
+
nativeDialogueWasOpened = false;
|
|
2048
|
+
answerDuration = 0;
|
|
2049
|
+
/**
|
|
2050
|
+
* @throws Error
|
|
2051
|
+
* @param element
|
|
2052
|
+
* @param options
|
|
2053
|
+
*/
|
|
2054
|
+
constructor(element, options) {
|
|
2055
|
+
super(element, options);
|
|
2056
|
+
this.elementRect = this.element.getBoundingClientRect();
|
|
2057
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
2058
|
+
this.percentFillMask = this.element.querySelector(".percent-filled-variants-view-group-mask");
|
|
2059
|
+
this.maskedVariants = slice.call(this.element.querySelectorAll(".variants-box .variants-view-group.percent-filled-variants-view-group .variant-view"));
|
|
2060
|
+
this.variantsViewGroup = getValueOrException(this.element.querySelector(".variants-box .variants-view-group:not(.percent-filled-variants-view-group)"), "Empty variantsViewGroup");
|
|
2061
|
+
this.variants = slice.call(this.variantsViewGroup.querySelectorAll(".variant-view"));
|
|
2062
|
+
this.variantsTexts = [];
|
|
2063
|
+
forEach(this.variants, (element, index) => {
|
|
2064
|
+
const label = element.querySelector(".label");
|
|
2065
|
+
if (label) {
|
|
2066
|
+
this.variantsTexts.push(label.textContent ?? "");
|
|
2067
|
+
}
|
|
2068
|
+
});
|
|
2069
|
+
this.isInvertedPercentFilledMaskDirection =
|
|
2070
|
+
this.element.classList.contains("theme-translucent") || this.element.classList.contains("base-theme-translucent");
|
|
2071
|
+
this.getUseResponseOnFirstButton = Boolean(getTagDataAsNumber(this.element, "getUserResponseOnFirstButton"));
|
|
2072
|
+
this.getUseResponseOnSecondButton = Boolean(getTagDataAsNumber(this.element, "getUserResponseOnSecondButton"));
|
|
2073
|
+
this.showClientTotalResult = Boolean(getTagDataAsNumber(this.element, "showClientTotalResult"));
|
|
2074
|
+
this.refreshUserData(this.options.localData);
|
|
2075
|
+
}
|
|
2076
|
+
refreshUserData(localData) {
|
|
2077
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
2078
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
2079
|
+
this.selectedVariant = undefined;
|
|
2080
|
+
if (this.localData) {
|
|
2081
|
+
if (this.localData["_p_g_" + this.elementId + "_sa"] !== undefined) {
|
|
2082
|
+
this._selectVariant(this.localData["_p_g_" + this.elementId + "_sa"], true);
|
|
2083
|
+
}
|
|
2084
|
+
else {
|
|
2085
|
+
this._clearVariantSelection();
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
this.firstOpenTime = new Date().getTime();
|
|
2089
|
+
this.nativeDialogueWasOpened = false;
|
|
2090
|
+
}
|
|
2091
|
+
_statEventPollAnswer() {
|
|
2092
|
+
this.answerDuration = new Date().getTime() - this.firstOpenTime;
|
|
2093
|
+
try {
|
|
2094
|
+
if (this.selectedVariant !== undefined) {
|
|
2095
|
+
var labelText = this.label?.textContent ?? "";
|
|
2096
|
+
var variantText = this.variantsTexts[this.selectedVariant] ? this.variantsTexts[this.selectedVariant] : "";
|
|
2097
|
+
this.sendStatisticEventToApp("w-poll-answer", {
|
|
2098
|
+
i: this.storyId,
|
|
2099
|
+
si: this.slideIndex,
|
|
2100
|
+
wi: this.elementId,
|
|
2101
|
+
wl: labelText,
|
|
2102
|
+
wa: this.selectedVariant,
|
|
2103
|
+
wal: variantText,
|
|
2104
|
+
d: this.answerDuration,
|
|
2105
|
+
}, {
|
|
2106
|
+
story_id: this.storyId,
|
|
2107
|
+
slide_index: this.slideIndex,
|
|
2108
|
+
widget_id: this.elementId,
|
|
2109
|
+
widget_label: labelText,
|
|
2110
|
+
widget_answer: this.selectedVariant,
|
|
2111
|
+
widget_answer_label: variantText,
|
|
2112
|
+
duration_ms: this.answerDuration,
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
catch (error) {
|
|
2117
|
+
console.error(error);
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
_statEventInputSave(responseText) {
|
|
2121
|
+
try {
|
|
2122
|
+
if (this.selectedVariant !== undefined) {
|
|
2123
|
+
var labelText = this.label?.textContent ?? "";
|
|
2124
|
+
var variantText = this.variantsTexts[this.selectedVariant] ? this.variantsTexts[this.selectedVariant] : "";
|
|
2125
|
+
this.sendStatisticEventToApp("w-poll-clarification", {
|
|
2126
|
+
i: this.storyId,
|
|
2127
|
+
si: this.slideIndex,
|
|
2128
|
+
wi: this.elementId,
|
|
2129
|
+
wl: labelText,
|
|
2130
|
+
wa: this.selectedVariant,
|
|
2131
|
+
wal: variantText,
|
|
2132
|
+
wv: responseText,
|
|
2133
|
+
d: this.answerDuration,
|
|
2134
|
+
}, {
|
|
2135
|
+
story_id: this.storyId,
|
|
2136
|
+
slide_index: this.slideIndex,
|
|
2137
|
+
widget_id: this.elementId,
|
|
2138
|
+
widget_label: labelText,
|
|
2139
|
+
widget_answer: this.selectedVariant,
|
|
2140
|
+
widget_answer_label: variantText,
|
|
2141
|
+
widget_value: responseText,
|
|
2142
|
+
duration_ms: this.answerDuration,
|
|
2143
|
+
});
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
catch (error) {
|
|
2147
|
+
console.error(error);
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
_selectVariant(index, filled = false) {
|
|
2151
|
+
if (this.variants[index]) {
|
|
2152
|
+
this.variants[index].classList.add("selected");
|
|
2153
|
+
}
|
|
2154
|
+
this.selectedVariant = index;
|
|
2155
|
+
this.localData["_p_g_" + this.elementId + "_sa"] = index;
|
|
2156
|
+
this.element.classList.add("done");
|
|
2157
|
+
this.element.classList.add("selected-" + this.selectedVariant);
|
|
2158
|
+
if (filled) {
|
|
2159
|
+
this.element.classList.add("filled");
|
|
2160
|
+
}
|
|
2161
|
+
if (this.showClientTotalResult) {
|
|
2162
|
+
this.element.classList.add("with-total-result");
|
|
2163
|
+
this.displayPercents(index, filled);
|
|
2164
|
+
}
|
|
2165
|
+
if (this.disableTimer) {
|
|
2166
|
+
this.env.setTimeout(() => {
|
|
2167
|
+
// todo poll - если виджет на первом слайде то при повторном заходе автоматически не стартует таймлайн слайда
|
|
2168
|
+
// только в web sdk такое
|
|
2169
|
+
// если поставить через setTimeout то все ок
|
|
2170
|
+
this.showNextSlide();
|
|
2171
|
+
});
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
_clearVariantSelection() {
|
|
2175
|
+
forEach(this.variants, function (variant) {
|
|
2176
|
+
variant.classList.remove("selected");
|
|
2177
|
+
});
|
|
2178
|
+
this.element.classList.remove("done");
|
|
2179
|
+
this.element.classList.remove("selected-" + this.selectedVariant);
|
|
2180
|
+
this.element.classList.remove("filled");
|
|
2181
|
+
this.selectedVariant = undefined;
|
|
2182
|
+
this.element.classList.remove("with-total-result");
|
|
2183
|
+
// this.displayPercents(index, filled);
|
|
2184
|
+
}
|
|
2185
|
+
selectVariant(variantView) {
|
|
2186
|
+
this.nativeDialogueWasOpened = false;
|
|
2187
|
+
if (this.selectedVariant !== undefined) {
|
|
2188
|
+
return true;
|
|
2189
|
+
}
|
|
2190
|
+
var index = this.variants.indexOf(variantView);
|
|
2191
|
+
if (index !== -1) {
|
|
2192
|
+
if (this.getUseResponseOnFirstButton && index === 0) {
|
|
2193
|
+
if (this.sdkApi.isAndroid) {
|
|
2194
|
+
this.slide.classList.add("blured");
|
|
2195
|
+
}
|
|
2196
|
+
this.slide.classList.add("data-input-editing");
|
|
2197
|
+
const dataString = this.element.dataset["clientdialogwidgetconfig"];
|
|
2198
|
+
this.selectedVariant = index;
|
|
2199
|
+
if (this.sdkApi.isExistsShowStoryTextInput && dataString) {
|
|
2200
|
+
const data = JSON.parse(dataString);
|
|
2201
|
+
data.size = getElementBounding(this.env, this.elementRect);
|
|
2202
|
+
if (!this.disableTimer) {
|
|
2203
|
+
this.sdkApi.pauseUI();
|
|
2204
|
+
}
|
|
2205
|
+
this.nativeDialogueWasOpened = false;
|
|
2206
|
+
try {
|
|
2207
|
+
data.text.value = data.text.value.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
2208
|
+
data.input.text.placeholder = data.input.text.placeholder.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
2209
|
+
data.configV2.main.question.text.value = data.configV2.main.question.text.value
|
|
2210
|
+
.replaceAll("\\n", "\n")
|
|
2211
|
+
.replaceAll("\\r", "\r")
|
|
2212
|
+
.replaceAll("\\t", "\t");
|
|
2213
|
+
data.configV2.main.input.text.placeholder = data.configV2.main.input.text.placeholder
|
|
2214
|
+
.replaceAll("\\n", "\n")
|
|
2215
|
+
.replaceAll("\\r", "\r")
|
|
2216
|
+
.replaceAll("\\t", "\t");
|
|
2217
|
+
}
|
|
2218
|
+
catch (e) {
|
|
2219
|
+
console.error(e);
|
|
2220
|
+
}
|
|
2221
|
+
this.sdkApi.showStoryTextInput(`${this.id}_first`, data);
|
|
2222
|
+
}
|
|
2223
|
+
this._statEventPollAnswer();
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
else if (this.getUseResponseOnSecondButton && index === 1) {
|
|
2227
|
+
if (this.sdkApi.isAndroid) {
|
|
2228
|
+
this.slide.classList.add("blured");
|
|
2229
|
+
}
|
|
2230
|
+
this.slide.classList.add("data-input-editing");
|
|
2231
|
+
const dataString = this.element.dataset["clientdialogwidgetconfig"];
|
|
2232
|
+
this.selectedVariant = index;
|
|
2233
|
+
if (this.sdkApi.isExistsShowStoryTextInput && dataString) {
|
|
2234
|
+
const data = JSON.parse(dataString);
|
|
2235
|
+
data.size = getElementBounding(this.env, this.elementRect);
|
|
2236
|
+
if (!this.disableTimer) {
|
|
2237
|
+
this.sdkApi.pauseUI();
|
|
2238
|
+
}
|
|
2239
|
+
try {
|
|
2240
|
+
data.text.value = data.text.value.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
2241
|
+
data.input.text.placeholder = data.input.text.placeholder.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
2242
|
+
data.configV2.main.question.text.value = data.configV2.main.question.text.value
|
|
2243
|
+
.replaceAll("\\n", "\n")
|
|
2244
|
+
.replaceAll("\\r", "\r")
|
|
2245
|
+
.replaceAll("\\t", "\t");
|
|
2246
|
+
data.configV2.main.input.text.placeholder = data.configV2.main.input.text.placeholder
|
|
2247
|
+
.replaceAll("\\n", "\n")
|
|
2248
|
+
.replaceAll("\\r", "\r")
|
|
2249
|
+
.replaceAll("\\t", "\t");
|
|
2250
|
+
}
|
|
2251
|
+
catch (e) {
|
|
2252
|
+
console.error(e);
|
|
2253
|
+
}
|
|
2254
|
+
this.sdkApi.showStoryTextInput(`${this.id}_second`, data);
|
|
2255
|
+
}
|
|
2256
|
+
this._statEventPollAnswer();
|
|
2257
|
+
return false;
|
|
2258
|
+
}
|
|
2259
|
+
else {
|
|
2260
|
+
this._selectVariant(index);
|
|
2261
|
+
this._statEventPollAnswer();
|
|
2262
|
+
}
|
|
2263
|
+
this.completeWidget();
|
|
2264
|
+
}
|
|
2265
|
+
return false;
|
|
2266
|
+
}
|
|
2267
|
+
_getVariantBoxInPercent(variantIndex) {
|
|
2268
|
+
var box = {
|
|
2269
|
+
sideOffset: 0,
|
|
2270
|
+
width: 0,
|
|
2271
|
+
};
|
|
2272
|
+
if (this.variantsViewGroup != null && variantIndex != null && this.variants[0] != null && this.variants[1] != null) {
|
|
2273
|
+
var viewGroupWidth = this.variantsViewGroup.clientWidth;
|
|
2274
|
+
if (viewGroupWidth > 0) {
|
|
2275
|
+
var offset = 0;
|
|
2276
|
+
var variantViewMinWidth = 0;
|
|
2277
|
+
// get min offset for variantView from variants-view-group
|
|
2278
|
+
var variantView = this.variants[variantIndex];
|
|
2279
|
+
var label = variantView.querySelector(".label");
|
|
2280
|
+
var percentLabel = variantView.querySelector(".percent-label");
|
|
2281
|
+
if (label != null && percentLabel != null) {
|
|
2282
|
+
var variantViewWidth = variantView.clientWidth;
|
|
2283
|
+
var labelOffset = (variantViewWidth - label.clientWidth) / 2;
|
|
2284
|
+
var percentLabelOffset = (variantViewWidth - percentLabel.clientWidth) / 2;
|
|
2285
|
+
offset = Math.min(labelOffset, percentLabelOffset);
|
|
2286
|
+
variantViewMinWidth = Math.max(label.clientWidth, percentLabel.clientWidth);
|
|
2287
|
+
}
|
|
2288
|
+
box.sideOffset = (offset / viewGroupWidth) * 100;
|
|
2289
|
+
box.width = (variantViewMinWidth / viewGroupWidth) * 100;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
return box;
|
|
2293
|
+
}
|
|
2294
|
+
displayPercents(selectedVariantIndex, filled = false) {
|
|
2295
|
+
let pollAllocation = [0, 0];
|
|
2296
|
+
let pollAllocationTs = undefined;
|
|
2297
|
+
const sharedData = this.sdkApi.getWidgetsSharedData(this.storyId, "poll" /* Widgets.Poll */);
|
|
2298
|
+
if (sharedData && sharedData[this.elementId] != null && (isObject(sharedData[this.elementId]) || isArray(sharedData[this.elementId]))) {
|
|
2299
|
+
pollAllocation = sharedData[this.elementId];
|
|
2300
|
+
if (isObject(sharedData[this.elementId])) {
|
|
2301
|
+
pollAllocation = slice.call(Object.values(sharedData[this.elementId]));
|
|
2302
|
+
}
|
|
2303
|
+
pollAllocationTs = sharedData.ts;
|
|
2304
|
+
}
|
|
2305
|
+
// todo debug
|
|
2306
|
+
// pollAllocation[0] = 10;
|
|
2307
|
+
// pollAllocation[1] = 20;
|
|
2308
|
+
var pollDoneAt = this.localData["_p_g_" + this.elementId + "_done_at"];
|
|
2309
|
+
if (pollAllocationTs === undefined || pollDoneAt === undefined || pollDoneAt > pollAllocationTs) {
|
|
2310
|
+
forEach(this.variants, (element, index) => {
|
|
2311
|
+
const key = index;
|
|
2312
|
+
if (pollAllocation[key] === undefined || !isNumber(pollAllocation[key])) {
|
|
2313
|
+
pollAllocation[key] = 0;
|
|
2314
|
+
}
|
|
2315
|
+
if (selectedVariantIndex === key) {
|
|
2316
|
+
++pollAllocation[key];
|
|
2317
|
+
}
|
|
2318
|
+
});
|
|
2319
|
+
}
|
|
2320
|
+
// calc percents
|
|
2321
|
+
var percents = [], total = 0;
|
|
2322
|
+
forEach(this.variants, (element, index) => {
|
|
2323
|
+
const key = index;
|
|
2324
|
+
if (pollAllocation[key] !== undefined) {
|
|
2325
|
+
if (!isNumber(pollAllocation[key])) {
|
|
2326
|
+
percents[key] = parseInt(String(pollAllocation[key]));
|
|
2327
|
+
}
|
|
2328
|
+
else {
|
|
2329
|
+
percents[key] = pollAllocation[key];
|
|
2330
|
+
}
|
|
2331
|
+
if (!isNumber(percents[key]) || isNaN(percents[key])) {
|
|
2332
|
+
percents[key] = 0;
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
else {
|
|
2336
|
+
percents[key] = 0;
|
|
2337
|
+
}
|
|
2338
|
+
total += percents[key];
|
|
2339
|
+
});
|
|
2340
|
+
for (var i = 0; i < percents.length; i++) {
|
|
2341
|
+
if (total !== 0) {
|
|
2342
|
+
percents[i] = Math.round((percents[i] / total) * 100);
|
|
2343
|
+
if (percents[i] > 100) {
|
|
2344
|
+
percents[i] = 100;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
else {
|
|
2348
|
+
percents[i] = 0;
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
var percentsTotal = function () {
|
|
2352
|
+
var acc = 0;
|
|
2353
|
+
for (var i = 0; i < percents.length; i++) {
|
|
2354
|
+
acc += percents[i];
|
|
2355
|
+
}
|
|
2356
|
+
return acc;
|
|
2357
|
+
};
|
|
2358
|
+
var start = new Date().getTime();
|
|
2359
|
+
while (percentsTotal() > 100) {
|
|
2360
|
+
percents[percents.length - 1]--;
|
|
2361
|
+
if (new Date().getTime() - start >= 1000) {
|
|
2362
|
+
break;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
var variantWithMinPercentsRelativeWidth = 0;
|
|
2366
|
+
var variantWithMinPercentsIndex = null;
|
|
2367
|
+
forEach(this.variants, (element, index) => {
|
|
2368
|
+
const key = index;
|
|
2369
|
+
var percent = percents[key];
|
|
2370
|
+
var variant = element;
|
|
2371
|
+
var maskedVariant = this.maskedVariants[key];
|
|
2372
|
+
if (this.selectedVariant === key) {
|
|
2373
|
+
variant.classList.add("selected");
|
|
2374
|
+
if (maskedVariant != null) {
|
|
2375
|
+
maskedVariant.classList.add("selected");
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
var percentLabel = variant.querySelector(".percent-label");
|
|
2379
|
+
if (percentLabel != null) {
|
|
2380
|
+
percentLabel.innerHTML = percent + "%";
|
|
2381
|
+
}
|
|
2382
|
+
var maskedPercentLabel = maskedVariant?.querySelector(".percent-label");
|
|
2383
|
+
if (maskedPercentLabel != null) {
|
|
2384
|
+
maskedPercentLabel.innerHTML = percent + "%";
|
|
2385
|
+
}
|
|
2386
|
+
});
|
|
2387
|
+
const cb = () => {
|
|
2388
|
+
if (this.percentFillMask != null &&
|
|
2389
|
+
this.variants[0] != null &&
|
|
2390
|
+
this.variants[1] != null &&
|
|
2391
|
+
this.selectedVariant != null &&
|
|
2392
|
+
percents[this.selectedVariant] != null) {
|
|
2393
|
+
var selectedVariantPercent = percents[this.selectedVariant];
|
|
2394
|
+
var limit = 0;
|
|
2395
|
+
var percent = 0;
|
|
2396
|
+
variantWithMinPercentsIndex = 0;
|
|
2397
|
+
if (percents[1] < percents[0]) {
|
|
2398
|
+
variantWithMinPercentsIndex = 1;
|
|
2399
|
+
}
|
|
2400
|
+
var boxPercents = this._getVariantBoxInPercent(variantWithMinPercentsIndex);
|
|
2401
|
+
variantWithMinPercentsRelativeWidth = boxPercents.width;
|
|
2402
|
+
var offset = 0;
|
|
2403
|
+
if (this.selectedVariant === 0) {
|
|
2404
|
+
if (this.isInvertedPercentFilledMaskDirection) {
|
|
2405
|
+
if (variantWithMinPercentsIndex === 1) {
|
|
2406
|
+
percent = Math.max(variantWithMinPercentsRelativeWidth, 100 - selectedVariantPercent);
|
|
2407
|
+
}
|
|
2408
|
+
else {
|
|
2409
|
+
limit = 100 - variantWithMinPercentsRelativeWidth;
|
|
2410
|
+
percent = Math.min(limit, 100 - selectedVariantPercent);
|
|
2411
|
+
}
|
|
2412
|
+
offset = (50 - percent) / 2;
|
|
2413
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-start", String(0));
|
|
2414
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-end", String(percent));
|
|
2415
|
+
this.element.style.setProperty("--variants-view-group-offset", String(offset));
|
|
2416
|
+
}
|
|
2417
|
+
else {
|
|
2418
|
+
if (variantWithMinPercentsIndex === 0) {
|
|
2419
|
+
// real variant percent or variantView min width
|
|
2420
|
+
percent = Math.max(selectedVariantPercent, variantWithMinPercentsRelativeWidth);
|
|
2421
|
+
}
|
|
2422
|
+
else {
|
|
2423
|
+
limit = 100 - variantWithMinPercentsRelativeWidth;
|
|
2424
|
+
percent = Math.min(limit, selectedVariantPercent);
|
|
2425
|
+
}
|
|
2426
|
+
offset = (50 - percent) / -2;
|
|
2427
|
+
// decrease alt color from start to firstVariant percents
|
|
2428
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-start", String(percent));
|
|
2429
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-end", String(0));
|
|
2430
|
+
this.element.style.setProperty("--variants-view-group-offset", String(offset));
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
else if (this.selectedVariant === 1) {
|
|
2434
|
+
if (this.isInvertedPercentFilledMaskDirection) {
|
|
2435
|
+
if (variantWithMinPercentsIndex === 0) {
|
|
2436
|
+
percent = Math.max(variantWithMinPercentsRelativeWidth, 100 - selectedVariantPercent);
|
|
2437
|
+
}
|
|
2438
|
+
else {
|
|
2439
|
+
limit = 100 - variantWithMinPercentsRelativeWidth;
|
|
2440
|
+
percent = Math.min(limit, 100 - selectedVariantPercent);
|
|
2441
|
+
}
|
|
2442
|
+
offset = (50 - percent) / -2;
|
|
2443
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-start", String(percent));
|
|
2444
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-end", String(0));
|
|
2445
|
+
this.element.style.setProperty("--variants-view-group-offset", String(offset));
|
|
2446
|
+
}
|
|
2447
|
+
else {
|
|
2448
|
+
// decrease alt color from end to secondVariant percents
|
|
2449
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-start", String(0));
|
|
2450
|
+
if (variantWithMinPercentsIndex === 1) {
|
|
2451
|
+
// real variant percent or variantView min width
|
|
2452
|
+
percent = Math.max(selectedVariantPercent, variantWithMinPercentsRelativeWidth);
|
|
2453
|
+
}
|
|
2454
|
+
else {
|
|
2455
|
+
limit = 100 - variantWithMinPercentsRelativeWidth;
|
|
2456
|
+
percent = Math.min(limit, selectedVariantPercent);
|
|
2457
|
+
}
|
|
2458
|
+
offset = (50 - percent) / 2;
|
|
2459
|
+
this.percentFillMask.style.setProperty("--selected-variant-view-clip-area-end", String(percent));
|
|
2460
|
+
this.element.style.setProperty("--variants-view-group-offset", String(offset));
|
|
2461
|
+
}
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
// if (filled) {
|
|
2466
|
+
// cb();
|
|
2467
|
+
// } else {
|
|
2468
|
+
// wait for percent render done (for calc correct variantView width)
|
|
2469
|
+
this.env.requestAnimationFrame(cb);
|
|
2470
|
+
// }
|
|
2471
|
+
}
|
|
2472
|
+
setUserText(text, buttonPosition) {
|
|
2473
|
+
this.slide.classList.remove("data-input-editing");
|
|
2474
|
+
this.slide.classList.remove("blured");
|
|
2475
|
+
if (this.selectedVariant != null) {
|
|
2476
|
+
this._selectVariant(this.selectedVariant);
|
|
2477
|
+
}
|
|
2478
|
+
if (!this.disableTimer && this.nativeDialogueWasOpened) {
|
|
2479
|
+
this.sdkApi.resumeUI();
|
|
2480
|
+
this.nativeDialogueWasOpened = false;
|
|
2481
|
+
}
|
|
2482
|
+
this.localData["_p_g_" + this.elementId + "_user_response_on_" + buttonPosition] = text;
|
|
2483
|
+
this.completeWidget();
|
|
2484
|
+
this._statEventInputSave(text);
|
|
2485
|
+
}
|
|
2486
|
+
completeWidget() {
|
|
2487
|
+
if (this.widgetDone) {
|
|
2488
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
2489
|
+
setTimeout(() => {
|
|
2490
|
+
this.widgetDone?.classList.remove("active");
|
|
2491
|
+
setTimeout(() => {
|
|
2492
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
2493
|
+
}, 250);
|
|
2494
|
+
}, 2000);
|
|
2495
|
+
}
|
|
2496
|
+
this.localData["_p_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
2497
|
+
// ответ на вопрос
|
|
2498
|
+
this.localData["_&ts_p_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
2499
|
+
this.setLocalData(this.localData, true);
|
|
2500
|
+
}
|
|
2501
|
+
isDone() {
|
|
2502
|
+
return this.localData["_p_g_" + this.elementId + "_done_at"] !== undefined;
|
|
2503
|
+
}
|
|
2504
|
+
slidePollIsDone() {
|
|
2505
|
+
return this.localData["_p_g_" + this.elementId + "_sa"] !== undefined;
|
|
2506
|
+
}
|
|
2507
|
+
static api = {
|
|
2508
|
+
...WidgetBase.api,
|
|
2509
|
+
initWidget: function (element, localData) {
|
|
2510
|
+
WidgetPoll.initWidgets((element, options) => new WidgetPoll(element, options), [element], localData);
|
|
2511
|
+
},
|
|
2512
|
+
/**
|
|
2513
|
+
* click
|
|
2514
|
+
*/
|
|
2515
|
+
select: function (element) {
|
|
2516
|
+
const widgetElement = element.closest(`.${WidgetPoll.widgetClassName}`);
|
|
2517
|
+
if (widgetElement) {
|
|
2518
|
+
const widget = WidgetPoll.getInstance(widgetElement);
|
|
2519
|
+
if (widget) {
|
|
2520
|
+
return widget.selectVariant(element);
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
return false;
|
|
2524
|
+
},
|
|
2525
|
+
slidePollIsDone: function (element) {
|
|
2526
|
+
const widget = WidgetPoll.getInstance(element);
|
|
2527
|
+
if (widget) {
|
|
2528
|
+
return widget.slidePollIsDone();
|
|
2529
|
+
}
|
|
2530
|
+
return true;
|
|
2531
|
+
},
|
|
2532
|
+
setUserData: function (id, text) {
|
|
2533
|
+
// id = widgetId_first || widgetId_second
|
|
2534
|
+
let correctWidgetId = id;
|
|
2535
|
+
let buttonPosition;
|
|
2536
|
+
if (id.endsWith("_first")) {
|
|
2537
|
+
buttonPosition = "first_button";
|
|
2538
|
+
correctWidgetId = id.replace(/_first$/, "");
|
|
2539
|
+
}
|
|
2540
|
+
else if (id.endsWith("_second")) {
|
|
2541
|
+
buttonPosition = "second_button";
|
|
2542
|
+
correctWidgetId = id.replace(/_second$/, "");
|
|
2543
|
+
}
|
|
2544
|
+
const widget = WidgetPoll.getInstanceById(correctWidgetId);
|
|
2545
|
+
if (widget && buttonPosition) {
|
|
2546
|
+
widget.setUserText(text, buttonPosition);
|
|
2547
|
+
}
|
|
2548
|
+
},
|
|
2549
|
+
};
|
|
2550
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
class WidgetPollLayers extends WidgetBase {
|
|
2554
|
+
static DEFAULTS = {
|
|
2555
|
+
slide: null,
|
|
2556
|
+
activateAfterCreate: false,
|
|
2557
|
+
create: false,
|
|
2558
|
+
localData: {},
|
|
2559
|
+
layers: [],
|
|
2560
|
+
};
|
|
2561
|
+
static widgetClassName = "narrative-element-poll-layers";
|
|
2562
|
+
label;
|
|
2563
|
+
variants;
|
|
2564
|
+
variantsTexts;
|
|
2565
|
+
selectedVariant;
|
|
2566
|
+
layers;
|
|
2567
|
+
constructor(element, options) {
|
|
2568
|
+
super(element, options);
|
|
2569
|
+
this.layers = this.options.layers;
|
|
2570
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
2571
|
+
this.variants = slice.call(this.element.querySelectorAll(".variants-box .variant-view"));
|
|
2572
|
+
this.variantsTexts = [];
|
|
2573
|
+
forEach(this.variants, (element, index) => {
|
|
2574
|
+
const label = element.querySelector(".label");
|
|
2575
|
+
if (label) {
|
|
2576
|
+
this.variantsTexts.push(label.textContent ?? "");
|
|
2577
|
+
}
|
|
2578
|
+
});
|
|
2579
|
+
this.selectedVariant = undefined;
|
|
2580
|
+
if (this.slidePollIsDone()) {
|
|
2581
|
+
this._selectVariant(this.localData["_pl_g_" + this.elementId + "_sa"]);
|
|
2582
|
+
}
|
|
2583
|
+
else {
|
|
2584
|
+
this._showLayout(this.layers, 0);
|
|
2585
|
+
}
|
|
2586
|
+
this.firstOpenTime = new Date().getTime();
|
|
2587
|
+
this.refreshUserData(this.options.localData);
|
|
2588
|
+
}
|
|
2589
|
+
refreshUserData(localData) { }
|
|
2590
|
+
_statEventPollVariant() {
|
|
2591
|
+
try {
|
|
2592
|
+
if (this.selectedVariant != null) {
|
|
2593
|
+
var labelText = this.label?.textContent ?? "";
|
|
2594
|
+
var variantText = this.variants[this.selectedVariant]?.textContent ?? "";
|
|
2595
|
+
var duration = new Date().getTime() - this.firstOpenTime;
|
|
2596
|
+
this.sendStatisticEventToApp("w-poll-layers-answer", {
|
|
2597
|
+
i: this.storyId,
|
|
2598
|
+
si: this.slideIndex,
|
|
2599
|
+
wi: this.elementId,
|
|
2600
|
+
wl: labelText,
|
|
2601
|
+
wa: this.selectedVariant,
|
|
2602
|
+
wal: variantText,
|
|
2603
|
+
d: duration,
|
|
2604
|
+
}, {
|
|
2605
|
+
story_id: this.storyId,
|
|
2606
|
+
slide_index: this.slideIndex,
|
|
2607
|
+
widget_id: this.elementId,
|
|
2608
|
+
widget_label: labelText,
|
|
2609
|
+
widget_variant: this.selectedVariant,
|
|
2610
|
+
widget_answer_label: variantText,
|
|
2611
|
+
duration_ms: duration,
|
|
2612
|
+
});
|
|
2613
|
+
}
|
|
2614
|
+
}
|
|
2615
|
+
catch (error) {
|
|
2616
|
+
console.error(error);
|
|
2617
|
+
}
|
|
2618
|
+
}
|
|
2619
|
+
_selectVariant(index, userAction = false) {
|
|
2620
|
+
if (this.variants[index]) {
|
|
2621
|
+
this.variants[index].classList.add("selected");
|
|
2622
|
+
}
|
|
2623
|
+
this.selectedVariant = index;
|
|
2624
|
+
this.localData["_pl_g_" + this.elementId + "_sa"] = index;
|
|
2625
|
+
this.element.classList.add("done");
|
|
2626
|
+
// main
|
|
2627
|
+
var layerIndex = 0;
|
|
2628
|
+
if (index === 0) {
|
|
2629
|
+
layerIndex = 1;
|
|
2630
|
+
}
|
|
2631
|
+
else if (index === 1) {
|
|
2632
|
+
layerIndex = 2;
|
|
2633
|
+
}
|
|
2634
|
+
this._showLayout(this.layers, layerIndex, userAction);
|
|
2635
|
+
if (this.disableTimer) {
|
|
2636
|
+
this.showNextSlide();
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
selectVariant(variant) {
|
|
2640
|
+
if (this.selectedVariant !== undefined) {
|
|
2641
|
+
return true;
|
|
2642
|
+
}
|
|
2643
|
+
var index = this.variants.indexOf(variant);
|
|
2644
|
+
if (index !== -1) {
|
|
2645
|
+
this._selectVariant(index, true);
|
|
2646
|
+
this.completeWidget();
|
|
2647
|
+
this._statEventPollVariant();
|
|
2648
|
+
}
|
|
2649
|
+
return false;
|
|
2650
|
+
}
|
|
2651
|
+
completeWidget() {
|
|
2652
|
+
if (this.widgetDone) {
|
|
2653
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
2654
|
+
setTimeout(() => {
|
|
2655
|
+
this.widgetDone?.classList.remove("active");
|
|
2656
|
+
setTimeout(() => {
|
|
2657
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
2658
|
+
}, 250);
|
|
2659
|
+
}, 2000);
|
|
2660
|
+
}
|
|
2661
|
+
this.localData["_pl_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
2662
|
+
// ответ на вопрос
|
|
2663
|
+
this.localData["_&ts_pl_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
2664
|
+
this.setLocalData(this.localData, true);
|
|
2665
|
+
}
|
|
2666
|
+
isDone() {
|
|
2667
|
+
return this.localData != null && this.localData["_pl_g_" + this.elementId + "_done_at"] !== undefined;
|
|
2668
|
+
}
|
|
2669
|
+
slidePollIsDone() {
|
|
2670
|
+
return this.localData != null && this.localData["_pl_g_" + this.elementId + "_sa"] !== undefined;
|
|
2671
|
+
}
|
|
2672
|
+
static api = {
|
|
2673
|
+
...WidgetBase.api,
|
|
2674
|
+
// signature variants
|
|
2675
|
+
// (widget, layers, undefined) - modern web sdk
|
|
2676
|
+
// (widget, undefined, layers) - old web sdk and rn
|
|
2677
|
+
// (widget, layers, localData) - native sdk
|
|
2678
|
+
initWidget: function (element, layers, localData) {
|
|
2679
|
+
if (layers === undefined && localData !== undefined) {
|
|
2680
|
+
// @ts-ignore
|
|
2681
|
+
layers = localData;
|
|
2682
|
+
localData = undefined;
|
|
2683
|
+
}
|
|
2684
|
+
WidgetPollLayers.initWidgets((element, options) => new WidgetPollLayers(element, { ...options, layers }), [element], localData);
|
|
2685
|
+
},
|
|
2686
|
+
/**
|
|
2687
|
+
* click on poll variant
|
|
2688
|
+
* @param element
|
|
2689
|
+
* @returns {boolean}
|
|
2690
|
+
*/
|
|
2691
|
+
select: function (element) {
|
|
2692
|
+
const widgetElement = element.closest(`.${WidgetPollLayers.widgetClassName}`);
|
|
2693
|
+
if (widgetElement) {
|
|
2694
|
+
const widget = WidgetPollLayers.getInstance(widgetElement);
|
|
2695
|
+
if (widget) {
|
|
2696
|
+
return widget.selectVariant(element);
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
return false;
|
|
2700
|
+
},
|
|
2701
|
+
};
|
|
2702
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
class WidgetQuest extends WidgetBase {
|
|
2706
|
+
static DEFAULTS = {
|
|
2707
|
+
slide: null,
|
|
2708
|
+
activateAfterCreate: false,
|
|
2709
|
+
create: false,
|
|
2710
|
+
localData: {},
|
|
2711
|
+
};
|
|
2712
|
+
static widgetClassName = "narrative-element-quest";
|
|
2713
|
+
selectedAnswer;
|
|
2714
|
+
label;
|
|
2715
|
+
variants;
|
|
2716
|
+
isWidget;
|
|
2717
|
+
slideCount;
|
|
2718
|
+
nonFinalSlide;
|
|
2719
|
+
finalSlide;
|
|
2720
|
+
constructor(element, options) {
|
|
2721
|
+
const isWidget = !hasClass(element, "narrative-slide");
|
|
2722
|
+
const elementIdGetter = (element) => getValueOrDefault(getTagData(element, "elementId"), "");
|
|
2723
|
+
const slideGetter = (element) => isWidget ? getValueOrException(element.closest(".narrative-slide"), "Empty slide") : element;
|
|
2724
|
+
super(element, options, elementIdGetter, slideGetter);
|
|
2725
|
+
this.isWidget = isWidget;
|
|
2726
|
+
this.slideCount = getTagDataAsNumber(this.slide, "slideCount") ?? 0;
|
|
2727
|
+
this.nonFinalSlide = Boolean(getTagDataAsNumber(this.slide, "nonFinalSlide") ?? 0);
|
|
2728
|
+
this.finalSlide = !this.isWidget && !this.nonFinalSlide;
|
|
2729
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
2730
|
+
this.variants = slice.call(this.element.querySelectorAll(".variants-box .variant-view"));
|
|
2731
|
+
this.selectedAnswer = undefined;
|
|
2732
|
+
// this.refreshUserData(this.options.localData);
|
|
2733
|
+
}
|
|
2734
|
+
refreshUserData(localData) { }
|
|
2735
|
+
setStorySessionValue(name, value) {
|
|
2736
|
+
try {
|
|
2737
|
+
var parent = this.element.closest(".stories-item");
|
|
2738
|
+
if (parent) {
|
|
2739
|
+
parent.dataset[name] = value;
|
|
2740
|
+
}
|
|
2741
|
+
else {
|
|
2742
|
+
//@ts-ignore
|
|
2743
|
+
this.env[name] = value;
|
|
2744
|
+
}
|
|
2745
|
+
}
|
|
2746
|
+
catch (e) {
|
|
2747
|
+
console.error(e);
|
|
2748
|
+
}
|
|
2749
|
+
}
|
|
2750
|
+
getStorySessionValue(name) {
|
|
2751
|
+
try {
|
|
2752
|
+
var parent = this.element.closest(".stories-item");
|
|
2753
|
+
if (parent) {
|
|
2754
|
+
return parent.dataset[name];
|
|
2755
|
+
}
|
|
2756
|
+
else {
|
|
2757
|
+
// @ts-ignore
|
|
2758
|
+
return this.env[name];
|
|
2759
|
+
}
|
|
2760
|
+
}
|
|
2761
|
+
catch (e) {
|
|
2762
|
+
console.error(e);
|
|
2763
|
+
return undefined;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
init() {
|
|
2767
|
+
if (this.localData) {
|
|
2768
|
+
if (this.localData["_qt_g_" + this.elementId + "_sa"] !== undefined) ;
|
|
2769
|
+
if (this.localData["_qt_fo_at"] === undefined) {
|
|
2770
|
+
this.localData["_qt_fo_at"] = Math.round(new Date().getTime() / 1000);
|
|
2771
|
+
this.setLocalData(this.localData, false);
|
|
2772
|
+
}
|
|
2773
|
+
var lastSlideIdx = this.localData["_qt_last_slide_idx"];
|
|
2774
|
+
if (lastSlideIdx !== undefined) {
|
|
2775
|
+
lastSlideIdx = parseInt(lastSlideIdx);
|
|
2776
|
+
if (lastSlideIdx >= 0 &&
|
|
2777
|
+
lastSlideIdx < this.slideCount &&
|
|
2778
|
+
lastSlideIdx !== this.slideIndex /*&& this.slideIndex === this.firstSlideWithQuestIndex()*/) {
|
|
2779
|
+
if (this.getStorySessionValue("__storyQuestSlideChanged") === undefined) {
|
|
2780
|
+
// global flag - был сделан переход на нужный слайд, больше не нужно повторять за эту сессию
|
|
2781
|
+
this.setStorySessionValue("__storyQuestSlideChanged", "1");
|
|
2782
|
+
if (this.sdkApi.isExistsShowStorySlide) {
|
|
2783
|
+
this.sdkApi.showStorySlide(lastSlideIdx);
|
|
2784
|
+
return false;
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
// если этого слайда нет в роутинге (сработал переход по таймеру в app)
|
|
2790
|
+
var routes = this._getRoutes();
|
|
2791
|
+
if (routes[0].indexOf(this.slideIndex) === -1 && this.finalSlide) {
|
|
2792
|
+
if (this.sdkApi.isExistsShowNextStory) {
|
|
2793
|
+
this.sdkApi.storyShowNext();
|
|
2794
|
+
return false;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
// сбор роутинга - все же в selectAnswer
|
|
2798
|
+
// + pointer - set in select answer and in simple history back naviation
|
|
2799
|
+
// Общее поле в сторис - latest slide with viewed quest item
|
|
2800
|
+
// только если находимся в диапазоне квеста
|
|
2801
|
+
this.localData["_qt_last_slide_idx"] = this.slideIndex;
|
|
2802
|
+
// global flag - был сделан переход на нужный слайд, больше не нужно повторять за эту сессию
|
|
2803
|
+
this.setStorySessionValue("__storyQuestSlideChanged", "1");
|
|
2804
|
+
// если перешли на слайд (через кнопку - на слайд например) то не будет истории в роутере
|
|
2805
|
+
// добавляем сами
|
|
2806
|
+
if (this.getLastSlideIndexFromRouteHistory() !== this.slideIndex) {
|
|
2807
|
+
this._addNewRouteHistory(this.slideIndex);
|
|
2808
|
+
}
|
|
2809
|
+
this.setLocalData(this.localData, true);
|
|
2810
|
+
}
|
|
2811
|
+
this.firstOpenTime = new Date().getTime();
|
|
2812
|
+
return true;
|
|
2813
|
+
}
|
|
2814
|
+
_selectAnswer(index, slideIndex) {
|
|
2815
|
+
// if (this.answers[index]) {
|
|
2816
|
+
// this.answers[index].classList.add('selected');
|
|
2817
|
+
// }
|
|
2818
|
+
this.selectedAnswer = index;
|
|
2819
|
+
if (this.localData["_qt_g_" + this.elementId + "_sa"] === undefined || !Array.isArray(this.localData["_qt_g_" + this.elementId + "_sa"])) {
|
|
2820
|
+
this.localData["_qt_g_" + this.elementId + "_sa"] = [];
|
|
2821
|
+
}
|
|
2822
|
+
this.localData["_qt_g_" + this.elementId + "_sa"].push([index, slideIndex, Math.round(new Date().getTime() / 1000)]);
|
|
2823
|
+
// ответ на вопрос
|
|
2824
|
+
this.localData["_&ts_qt_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
2825
|
+
this.element.classList.add("done");
|
|
2826
|
+
this._addNewRouteHistory(slideIndex);
|
|
2827
|
+
}
|
|
2828
|
+
selectAnswer(answer) {
|
|
2829
|
+
// if (this.selectedAnswer !== undefined) {
|
|
2830
|
+
// return true;
|
|
2831
|
+
// }
|
|
2832
|
+
var index = this.variants.indexOf(answer);
|
|
2833
|
+
if (index !== -1) {
|
|
2834
|
+
var slideIndex = getValueOrDefault(getTagDataAsNumber(this.variants[index], "score"), 0) - 1;
|
|
2835
|
+
this._selectAnswer(index, slideIndex);
|
|
2836
|
+
this.setLocalData(this.localData, true);
|
|
2837
|
+
this.env.setTimeout(() => {
|
|
2838
|
+
if (slideIndex >= 0 && slideIndex < this.slideCount && this.sdkApi.isExistsShowStorySlide) {
|
|
2839
|
+
// global flag - был сделан переход на нужный слайд, больше не нужно повторять за эту сессию
|
|
2840
|
+
this.setStorySessionValue("__storyQuestSlideChanged", "1");
|
|
2841
|
+
this.sdkApi.showStorySlide(slideIndex);
|
|
2842
|
+
}
|
|
2843
|
+
}, 100);
|
|
2844
|
+
}
|
|
2845
|
+
return true;
|
|
2846
|
+
}
|
|
2847
|
+
isDone() {
|
|
2848
|
+
return this.localData["_qt_done_at"] !== undefined && this.selectedAnswer !== undefined;
|
|
2849
|
+
}
|
|
2850
|
+
slideQuestIsDone() {
|
|
2851
|
+
return this.localData["_qt_g_" + this.elementId + "_sa"] !== undefined && this.selectedAnswer !== undefined;
|
|
2852
|
+
}
|
|
2853
|
+
firstSlideWithQuestIndex() {
|
|
2854
|
+
return getTagDataAsNumber(this.slide, "firstSlideWithQuest") ?? 0;
|
|
2855
|
+
}
|
|
2856
|
+
lastSlideWithQuestIndex() {
|
|
2857
|
+
return getTagDataAsNumber(this.slide, "lastSlideWithQuest") ?? 0;
|
|
2858
|
+
}
|
|
2859
|
+
_getRoutes() {
|
|
2860
|
+
var routes = this.localData["_qt_routes"];
|
|
2861
|
+
if (!Array.isArray(routes)) {
|
|
2862
|
+
routes = [[0], 0];
|
|
2863
|
+
}
|
|
2864
|
+
return routes;
|
|
2865
|
+
}
|
|
2866
|
+
_addNewRouteHistory(route) {
|
|
2867
|
+
var routes = this._getRoutes();
|
|
2868
|
+
var _routes = routes[0].slice(0, routes[1] + 1);
|
|
2869
|
+
routes[0] = _routes.concat([route]);
|
|
2870
|
+
routes[1] = routes[0].length - 1;
|
|
2871
|
+
this.localData["_qt_routes"] = routes;
|
|
2872
|
+
}
|
|
2873
|
+
_routeMvPtrBack() {
|
|
2874
|
+
var routes = this._getRoutes();
|
|
2875
|
+
var newPtr = routes[1] - 1;
|
|
2876
|
+
if (newPtr >= 0 && routes[0][newPtr] !== undefined) {
|
|
2877
|
+
routes[1] = newPtr;
|
|
2878
|
+
this.localData["_qt_routes"] = routes;
|
|
2879
|
+
this.setLocalData(this.localData, true);
|
|
2880
|
+
return routes[0][newPtr];
|
|
2881
|
+
}
|
|
2882
|
+
return false;
|
|
2883
|
+
}
|
|
2884
|
+
getLastSlideIndexFromRouteHistory() {
|
|
2885
|
+
var routes = this._getRoutes();
|
|
2886
|
+
return routes[0][routes[1]];
|
|
2887
|
+
}
|
|
2888
|
+
handleRouteClick(event) {
|
|
2889
|
+
// event: direction ('backward', 'forward') slideIndex, slideCount
|
|
2890
|
+
var directionForward = event.direction === "forward";
|
|
2891
|
+
event.direction === "backward";
|
|
2892
|
+
if (this.isWidget) {
|
|
2893
|
+
if (directionForward) {
|
|
2894
|
+
return;
|
|
2895
|
+
}
|
|
2896
|
+
else {
|
|
2897
|
+
if (event.slideIndex === 0) {
|
|
2898
|
+
// can click back
|
|
2899
|
+
event.click();
|
|
2900
|
+
}
|
|
2901
|
+
else {
|
|
2902
|
+
// by routing - move back
|
|
2903
|
+
var moveTo = this._routeMvPtrBack();
|
|
2904
|
+
if (moveTo !== false && moveTo >= 0 && moveTo < event.slideCount && this.sdkApi.isExistsShowStorySlide) {
|
|
2905
|
+
this.sdkApi.showStorySlide(moveTo);
|
|
2906
|
+
}
|
|
2907
|
+
if (moveTo === false && this.sdkApi.isExistsShowStorySlide) {
|
|
2908
|
+
// allow move to start - for broken route history
|
|
2909
|
+
this.sdkApi.showStorySlide(0);
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
return;
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
else {
|
|
2916
|
+
// slides without quest form
|
|
2917
|
+
// simple slide case
|
|
2918
|
+
if (this.nonFinalSlide || event.slideIndex < this.firstSlideWithQuestIndex()) {
|
|
2919
|
+
if (directionForward) {
|
|
2920
|
+
var nextSlideIndex = event.slideIndex + 1;
|
|
2921
|
+
if (nextSlideIndex < this.slideCount) {
|
|
2922
|
+
this._addNewRouteHistory(nextSlideIndex);
|
|
2923
|
+
this.setLocalData(this.localData, true);
|
|
2924
|
+
this.sdkApi.showStorySlide(nextSlideIndex);
|
|
2925
|
+
}
|
|
2926
|
+
else {
|
|
2927
|
+
if (this.sdkApi.isExistsShowNextStory) {
|
|
2928
|
+
this.sdkApi.storyShowNext();
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
else {
|
|
2933
|
+
if (event.slideIndex === 0) {
|
|
2934
|
+
// move to prev slide
|
|
2935
|
+
event.click();
|
|
2936
|
+
}
|
|
2937
|
+
else {
|
|
2938
|
+
// by routing - move back
|
|
2939
|
+
var moveTo = this._routeMvPtrBack();
|
|
2940
|
+
if (moveTo !== false && moveTo >= 0 && moveTo < event.slideCount && this.sdkApi.isExistsShowStorySlide) {
|
|
2941
|
+
this.sdkApi.showStorySlide(moveTo);
|
|
2942
|
+
}
|
|
2943
|
+
if (moveTo === false && this.sdkApi.isExistsShowStorySlide) {
|
|
2944
|
+
// allow move to start - for broken route history
|
|
2945
|
+
this.sdkApi.showStorySlide(0);
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
}
|
|
2950
|
+
else {
|
|
2951
|
+
// quest final slide
|
|
2952
|
+
if (directionForward) {
|
|
2953
|
+
// если клик вперед по финальному слайду из любой ветки - то выходим из сторис
|
|
2954
|
+
// var nextSlideIndex = this.lastSlideWithQuestIndex() + 1;
|
|
2955
|
+
// if (nextSlideIndex < this.slideCount) {
|
|
2956
|
+
// this._addNewRouteHistory(nextSlideIndex);
|
|
2957
|
+
// setLocalData(this.localData, true);
|
|
2958
|
+
// window._showNarrativeSlide(nextSlideIndex);
|
|
2959
|
+
// } else {
|
|
2960
|
+
if (this.sdkApi.isExistsShowNextStory) {
|
|
2961
|
+
this.sdkApi.storyShowNext();
|
|
2962
|
+
}
|
|
2963
|
+
// }
|
|
2964
|
+
}
|
|
2965
|
+
else {
|
|
2966
|
+
// by routing - move back
|
|
2967
|
+
var moveTo = this._routeMvPtrBack();
|
|
2968
|
+
if (moveTo !== false && moveTo >= 0 && moveTo < event.slideCount && this.sdkApi.isExistsShowStorySlide) {
|
|
2969
|
+
this.sdkApi.showStorySlide(moveTo);
|
|
2970
|
+
}
|
|
2971
|
+
if (moveTo === false && this.sdkApi.isExistsShowStorySlide) {
|
|
2972
|
+
// allow move to start - for broken route history
|
|
2973
|
+
this.sdkApi.showStorySlide(0);
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
static api = {
|
|
2980
|
+
...WidgetBase.api,
|
|
2981
|
+
initWidget: function (element, localData) {
|
|
2982
|
+
return new Promise(function (resolve, reject) {
|
|
2983
|
+
WidgetQuest.initWidgets((element, options) => new WidgetQuest(element, options), [element], localData).then(localData => {
|
|
2984
|
+
const widget = WidgetQuest.getInstance(element);
|
|
2985
|
+
if (widget) {
|
|
2986
|
+
resolve(widget.init());
|
|
2987
|
+
}
|
|
2988
|
+
else {
|
|
2989
|
+
resolve(true);
|
|
2990
|
+
}
|
|
2991
|
+
});
|
|
2992
|
+
});
|
|
2993
|
+
},
|
|
2994
|
+
select: function (element) {
|
|
2995
|
+
const widgetElement = element.closest(`.${WidgetQuest.widgetClassName}`);
|
|
2996
|
+
if (widgetElement) {
|
|
2997
|
+
const widget = WidgetQuest.getInstance(widgetElement);
|
|
2998
|
+
if (widget) {
|
|
2999
|
+
return widget.selectAnswer(element);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
return false;
|
|
3003
|
+
},
|
|
3004
|
+
slideTestIsDone: function (element) {
|
|
3005
|
+
const widget = WidgetQuest.getInstance(element);
|
|
3006
|
+
if (widget) {
|
|
3007
|
+
return widget.slideQuestIsDone();
|
|
3008
|
+
}
|
|
3009
|
+
return true;
|
|
3010
|
+
},
|
|
3011
|
+
handleRouteClick: function (element, event) {
|
|
3012
|
+
const widget = WidgetQuest.getInstance(element);
|
|
3013
|
+
if (widget) {
|
|
3014
|
+
widget.handleRouteClick(event);
|
|
3015
|
+
}
|
|
3016
|
+
},
|
|
3017
|
+
};
|
|
3018
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
class WidgetQuiz extends WidgetBase {
|
|
3022
|
+
static DEFAULTS = {
|
|
3023
|
+
slide: null,
|
|
3024
|
+
activateAfterCreate: false,
|
|
3025
|
+
create: false,
|
|
3026
|
+
localData: {},
|
|
3027
|
+
};
|
|
3028
|
+
static widgetClassName = "narrative-element-quiz";
|
|
3029
|
+
question;
|
|
3030
|
+
answers;
|
|
3031
|
+
questionCount;
|
|
3032
|
+
selectedAnswer;
|
|
3033
|
+
constructor(element, options) {
|
|
3034
|
+
super(element, options);
|
|
3035
|
+
this.question = this.element.querySelector(".label-view .label");
|
|
3036
|
+
this.answers = slice.call(this.element.querySelectorAll(".variants-box .variant-view-group"));
|
|
3037
|
+
this.questionCount = getValueOrException(getTagDataAsNumber(this.slide, "quizCount"), "Empty quizCount");
|
|
3038
|
+
this.refreshUserData(this.options.localData);
|
|
3039
|
+
}
|
|
3040
|
+
refreshUserData(localData) {
|
|
3041
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
3042
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
3043
|
+
this.selectedAnswer = undefined;
|
|
3044
|
+
if (this.localData) {
|
|
3045
|
+
if (this.localData["_q_g_" + this.elementId + "_sa"] !== undefined) {
|
|
3046
|
+
this._selectAnswer(this.localData["_q_g_" + this.elementId + "_sa"]);
|
|
3047
|
+
this.constructor.setLocalData(this.localData, false);
|
|
3048
|
+
}
|
|
3049
|
+
else {
|
|
3050
|
+
this._clearAnswerSelection();
|
|
3051
|
+
}
|
|
3052
|
+
if (this.localData["_q_fo_at"] === undefined) {
|
|
3053
|
+
this.localData["_q_fo_at"] = Math.round(new Date().getTime() / 1000);
|
|
3054
|
+
this.constructor.setLocalData(this.localData, false);
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
this.firstOpenTime = new Date().getTime();
|
|
3058
|
+
}
|
|
3059
|
+
_selectAnswer(index) {
|
|
3060
|
+
// var hintContainer = null;
|
|
3061
|
+
// var hintContainerHeight = null;
|
|
3062
|
+
if (this.answers[index]) {
|
|
3063
|
+
this.answers[index].classList.add("selected");
|
|
3064
|
+
// hintContainer = this.answers[index].nextSibling;
|
|
3065
|
+
// if (hintContainer && hintContainer.classList.contains('narrative-element-quiz-answer-hint-container')) {
|
|
3066
|
+
// hintContainerHeight = hintContainer.getBoundingClientRect().height;
|
|
3067
|
+
// hintContainer.style.height = 0;
|
|
3068
|
+
// }
|
|
3069
|
+
}
|
|
3070
|
+
this.selectedAnswer = index;
|
|
3071
|
+
this.localData["_q_g_" + this.elementId + "_sa"] = index;
|
|
3072
|
+
this.element.classList.add("done");
|
|
3073
|
+
this.env.requestAnimationFrame(() => {
|
|
3074
|
+
if (this.submitButtonAnimatedView != null && this.submitButtonViewHeight != null) {
|
|
3075
|
+
this.submitButtonAnimatedView.style.maxHeight = `${this.submitButtonViewHeight}px`;
|
|
3076
|
+
}
|
|
3077
|
+
});
|
|
3078
|
+
// if (hintContainer && hintContainerHeight && window.requestAnimationFrame) {
|
|
3079
|
+
// requestAnimationFrame(function() {
|
|
3080
|
+
// requestAnimationFrame(function() {
|
|
3081
|
+
// hintContainer.style.height = hintContainerHeight + 'px';
|
|
3082
|
+
// })
|
|
3083
|
+
// })
|
|
3084
|
+
// }
|
|
3085
|
+
if (this.disableTimer) {
|
|
3086
|
+
this.showNextSlide();
|
|
3087
|
+
}
|
|
3088
|
+
}
|
|
3089
|
+
_clearAnswerSelection() {
|
|
3090
|
+
forEach(this.answers, function (answer) {
|
|
3091
|
+
answer.classList.remove("selected");
|
|
3092
|
+
});
|
|
3093
|
+
this.selectedAnswer = undefined;
|
|
3094
|
+
this.element.classList.remove("done");
|
|
3095
|
+
this.env.requestAnimationFrame(() => {
|
|
3096
|
+
if (this.submitButtonAnimatedView != null) {
|
|
3097
|
+
this.submitButtonAnimatedView.style.maxHeight = "0px";
|
|
3098
|
+
}
|
|
3099
|
+
});
|
|
3100
|
+
}
|
|
3101
|
+
selectAnswer(answer) {
|
|
3102
|
+
if (this.selectedAnswer !== undefined) {
|
|
3103
|
+
return true;
|
|
3104
|
+
}
|
|
3105
|
+
const selectedAnswerIndex = this.answers.indexOf(answer);
|
|
3106
|
+
if (selectedAnswerIndex !== -1) {
|
|
3107
|
+
this._selectAnswer(selectedAnswerIndex);
|
|
3108
|
+
var isCorrect = this.answers[selectedAnswerIndex].classList.contains("check");
|
|
3109
|
+
this.localData["q_score"] = (this.localData["q_score"] === undefined ? 0 : this.localData["q_score"]) + (isCorrect ? 1 : 0);
|
|
3110
|
+
var answeredQuestion = 0;
|
|
3111
|
+
for (var key in this.localData) {
|
|
3112
|
+
if (this.localData.hasOwnProperty(key)) {
|
|
3113
|
+
if (/^_q_g_[A-z0-9-_]+_sa$/.test(key)) {
|
|
3114
|
+
answeredQuestion++;
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
if (this.localData["_q_fa_at"] === undefined) {
|
|
3119
|
+
this.localData["_q_fa_at"] = Math.round(new Date().getTime() / 1000);
|
|
3120
|
+
}
|
|
3121
|
+
if (answeredQuestion === this.questionCount) {
|
|
3122
|
+
this.localData["_q_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
3123
|
+
}
|
|
3124
|
+
// ответ на вопрос
|
|
3125
|
+
this.localData["_&ts_q_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
3126
|
+
this.setLocalData(this.localData, true);
|
|
3127
|
+
if (this.widgetDone) {
|
|
3128
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
3129
|
+
const self = this;
|
|
3130
|
+
setTimeout(function () {
|
|
3131
|
+
self.widgetDone?.classList.remove("active");
|
|
3132
|
+
setTimeout(function () {
|
|
3133
|
+
self.widgetDone?.classList.remove("opacity-active");
|
|
3134
|
+
}, 250);
|
|
3135
|
+
}, 2000);
|
|
3136
|
+
}
|
|
3137
|
+
try {
|
|
3138
|
+
var questionText = this.question ? this.question.textContent ?? "" : "";
|
|
3139
|
+
let answerText = "";
|
|
3140
|
+
if (this.answers[selectedAnswerIndex]) {
|
|
3141
|
+
const answerLabel = this.answers[selectedAnswerIndex].querySelector(".variant-view .label");
|
|
3142
|
+
if (answerLabel != null && answerLabel.textContent != null) {
|
|
3143
|
+
answerText = answerLabel.textContent;
|
|
3144
|
+
}
|
|
3145
|
+
}
|
|
3146
|
+
var duration = new Date().getTime() - this.firstOpenTime;
|
|
3147
|
+
WidgetBase.sendStatisticEventToApp("w-quiz-answer", {
|
|
3148
|
+
i: this.storyId,
|
|
3149
|
+
si: this.slideIndex,
|
|
3150
|
+
wi: this.elementId,
|
|
3151
|
+
wl: questionText,
|
|
3152
|
+
wa: selectedAnswerIndex,
|
|
3153
|
+
wal: answerText,
|
|
3154
|
+
d: duration,
|
|
3155
|
+
}, {
|
|
3156
|
+
story_id: this.storyId,
|
|
3157
|
+
slide_index: this.slideIndex,
|
|
3158
|
+
widget_id: this.elementId,
|
|
3159
|
+
widget_label: questionText,
|
|
3160
|
+
widget_answer: selectedAnswerIndex,
|
|
3161
|
+
widget_answer_label: answerText,
|
|
3162
|
+
duration_ms: duration,
|
|
3163
|
+
});
|
|
3164
|
+
}
|
|
3165
|
+
catch (error) {
|
|
3166
|
+
console.error(error);
|
|
3167
|
+
}
|
|
3168
|
+
}
|
|
3169
|
+
return false;
|
|
3170
|
+
}
|
|
3171
|
+
isDone() {
|
|
3172
|
+
return this.localData["_q_done_at"] !== undefined;
|
|
3173
|
+
}
|
|
3174
|
+
slideQuizIsDone() {
|
|
3175
|
+
return this.localData["_q_g_" + this.elementId + "_sa"] !== undefined;
|
|
3176
|
+
}
|
|
3177
|
+
static api = {
|
|
3178
|
+
...WidgetBase.api,
|
|
3179
|
+
initWidget: function (element, localData) {
|
|
3180
|
+
WidgetQuiz.initWidgets((element, options) => new WidgetQuiz(element, options), [element], localData);
|
|
3181
|
+
},
|
|
3182
|
+
/**
|
|
3183
|
+
* click on quiz answer
|
|
3184
|
+
*/
|
|
3185
|
+
select: function (element) {
|
|
3186
|
+
const widgetElement = element.closest(`.${WidgetQuiz.widgetClassName}`);
|
|
3187
|
+
if (widgetElement) {
|
|
3188
|
+
const widget = WidgetQuiz.getInstance(widgetElement);
|
|
3189
|
+
if (widget) {
|
|
3190
|
+
return widget.selectAnswer(element);
|
|
3191
|
+
}
|
|
3192
|
+
}
|
|
3193
|
+
return false;
|
|
3194
|
+
},
|
|
3195
|
+
slideQuizIsDone: function (element) {
|
|
3196
|
+
const widget = WidgetQuiz.getInstance(element);
|
|
3197
|
+
if (widget) {
|
|
3198
|
+
return widget.slideQuizIsDone();
|
|
3199
|
+
}
|
|
3200
|
+
return true;
|
|
3201
|
+
},
|
|
3202
|
+
};
|
|
3203
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
3204
|
+
}
|
|
3205
|
+
|
|
3206
|
+
class WidgetQuizGrouped extends WidgetBase {
|
|
3207
|
+
static DEFAULTS = {
|
|
3208
|
+
slide: null,
|
|
3209
|
+
activateAfterCreate: false,
|
|
3210
|
+
create: false,
|
|
3211
|
+
localData: {},
|
|
3212
|
+
};
|
|
3213
|
+
static widgetClassName = "narrative-element-quiz-grouped";
|
|
3214
|
+
question;
|
|
3215
|
+
answers;
|
|
3216
|
+
questionCount;
|
|
3217
|
+
selectedAnswer;
|
|
3218
|
+
/**
|
|
3219
|
+
* @throws Error
|
|
3220
|
+
* @param element
|
|
3221
|
+
* @param options
|
|
3222
|
+
*/
|
|
3223
|
+
constructor(element, options) {
|
|
3224
|
+
super(element, options);
|
|
3225
|
+
this.question = this.element.querySelector(".label-view .label");
|
|
3226
|
+
this.answers = slice.call(this.element.querySelectorAll(".variants-box .variant-view-group"));
|
|
3227
|
+
this.questionCount = getValueOrException(getTagDataAsNumber(this.slide, "quizCount"), "Empty quizCount");
|
|
3228
|
+
this.refreshUserData(this.options.localData);
|
|
3229
|
+
}
|
|
3230
|
+
refreshUserData(localData) {
|
|
3231
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
3232
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
3233
|
+
this.selectedAnswer = undefined;
|
|
3234
|
+
if (this.localData) {
|
|
3235
|
+
if (this.localData["_q_gg_" + this.elementId + "_sa"] !== undefined) {
|
|
3236
|
+
this._selectAnswer(this.localData["_q_gg_" + this.elementId + "_sa"]);
|
|
3237
|
+
// this._updateScore(this.localData['_q_gg_' + this.elementId + '_sa']);
|
|
3238
|
+
this.setLocalData(this.localData, false);
|
|
3239
|
+
}
|
|
3240
|
+
else {
|
|
3241
|
+
this._clearAnswerSelection();
|
|
3242
|
+
}
|
|
3243
|
+
if (this.localData["_qg_fo_at"] === undefined) {
|
|
3244
|
+
this.localData["_qg_fo_at"] = Math.round(new Date().getTime() / 1000);
|
|
3245
|
+
this.setLocalData(this.localData, false);
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3248
|
+
this.firstOpenTime = new Date().getTime();
|
|
3249
|
+
}
|
|
3250
|
+
_selectAnswer(index) {
|
|
3251
|
+
if (this.answers[index]) {
|
|
3252
|
+
this.answers[index].classList.add("selected");
|
|
3253
|
+
}
|
|
3254
|
+
this.selectedAnswer = index;
|
|
3255
|
+
this.localData["_q_gg_" + this.elementId + "_sa"] = index;
|
|
3256
|
+
this.element.classList.add("done");
|
|
3257
|
+
this.env.requestAnimationFrame(() => {
|
|
3258
|
+
if (this.submitButtonAnimatedView != null && this.submitButtonViewHeight != null) {
|
|
3259
|
+
this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
|
|
3260
|
+
}
|
|
3261
|
+
});
|
|
3262
|
+
if (this.disableTimer) {
|
|
3263
|
+
this.showNextSlide();
|
|
3264
|
+
}
|
|
3265
|
+
}
|
|
3266
|
+
_clearAnswerSelection() {
|
|
3267
|
+
forEach(this.answers, function (answer) {
|
|
3268
|
+
answer.classList.remove("selected");
|
|
3269
|
+
});
|
|
3270
|
+
this.selectedAnswer = undefined;
|
|
3271
|
+
this.element.classList.remove("done");
|
|
3272
|
+
this.env.requestAnimationFrame(() => {
|
|
3273
|
+
if (this.submitButtonAnimatedView != null) {
|
|
3274
|
+
this.submitButtonAnimatedView.style.maxHeight = "0px";
|
|
3275
|
+
}
|
|
3276
|
+
});
|
|
3277
|
+
}
|
|
3278
|
+
_updateScore(index) {
|
|
3279
|
+
const answerValue = getValueOrDefault(getTagDataAsNumber(this.answers[index], "value"), index);
|
|
3280
|
+
if (this.localData["qg_score"] == null) {
|
|
3281
|
+
this.localData["qg_score"] = {};
|
|
3282
|
+
}
|
|
3283
|
+
var sum = 0;
|
|
3284
|
+
for (var i = 0; i < this.answers.length; i++) {
|
|
3285
|
+
if (this.localData["qg_score"][i] == null) {
|
|
3286
|
+
this.localData["qg_score"][i] = 0;
|
|
3287
|
+
}
|
|
3288
|
+
sum += this.localData["qg_score"][i];
|
|
3289
|
+
}
|
|
3290
|
+
// если еще не ответили на все
|
|
3291
|
+
if (sum < this.questionCount) {
|
|
3292
|
+
this.localData["qg_score"][answerValue] += 1;
|
|
3293
|
+
var answeredQuestion = 0;
|
|
3294
|
+
for (var key in this.localData) {
|
|
3295
|
+
if (this.localData.hasOwnProperty(key)) {
|
|
3296
|
+
if (/^_q_gg_[A-z0-9-_]+_sa$/.test(key)) {
|
|
3297
|
+
answeredQuestion++;
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
}
|
|
3301
|
+
if (this.localData["_qg_fa_at"] === undefined) {
|
|
3302
|
+
this.localData["_qg_fa_at"] = Math.round(new Date().getTime() / 1000);
|
|
3303
|
+
}
|
|
3304
|
+
if (this.localData["_qg_done_at"] === undefined) {
|
|
3305
|
+
if (answeredQuestion === this.questionCount) {
|
|
3306
|
+
this.localData["_qg_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
3307
|
+
}
|
|
3308
|
+
}
|
|
3309
|
+
// ответ на вопрос
|
|
3310
|
+
this.localData["_&ts_qg_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
3311
|
+
this.setLocalData(this.localData, true);
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
selectAnswer(answer) {
|
|
3315
|
+
if (this.selectedAnswer != null) {
|
|
3316
|
+
return true;
|
|
3317
|
+
}
|
|
3318
|
+
const selectedAnswerIndex = this.answers.indexOf(answer);
|
|
3319
|
+
if (selectedAnswerIndex !== -1) {
|
|
3320
|
+
this._selectAnswer(selectedAnswerIndex);
|
|
3321
|
+
this._updateScore(selectedAnswerIndex);
|
|
3322
|
+
if (this.widgetDone) {
|
|
3323
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
3324
|
+
setTimeout(() => {
|
|
3325
|
+
this.widgetDone?.classList.remove("active");
|
|
3326
|
+
setTimeout(() => {
|
|
3327
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
3328
|
+
}, 250);
|
|
3329
|
+
}, 2000);
|
|
3330
|
+
}
|
|
3331
|
+
try {
|
|
3332
|
+
var questionText = this.question ? this.question.textContent ?? "" : "";
|
|
3333
|
+
var answerText = "";
|
|
3334
|
+
if (this.answers[selectedAnswerIndex]) {
|
|
3335
|
+
var answerLabel = this.answers[selectedAnswerIndex].querySelector(".variant-view .label");
|
|
3336
|
+
if (answerLabel != null) {
|
|
3337
|
+
answerText = answerLabel.textContent ?? "";
|
|
3338
|
+
}
|
|
3339
|
+
}
|
|
3340
|
+
var duration = new Date().getTime() - this.firstOpenTime;
|
|
3341
|
+
WidgetBase.sendStatisticEventToApp("w-quiz-grouped-answer", {
|
|
3342
|
+
i: this.storyId,
|
|
3343
|
+
si: this.slideIndex,
|
|
3344
|
+
wi: this.elementId,
|
|
3345
|
+
wl: questionText,
|
|
3346
|
+
wa: selectedAnswerIndex,
|
|
3347
|
+
wal: answerText,
|
|
3348
|
+
d: duration,
|
|
3349
|
+
}, {
|
|
3350
|
+
story_id: this.storyId,
|
|
3351
|
+
slide_index: this.slideIndex,
|
|
3352
|
+
widget_id: this.elementId,
|
|
3353
|
+
widget_label: questionText,
|
|
3354
|
+
widget_answer: selectedAnswerIndex,
|
|
3355
|
+
widget_answer_label: answerText,
|
|
3356
|
+
duration_ms: duration,
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
catch (error) {
|
|
3360
|
+
console.error(error);
|
|
3361
|
+
}
|
|
3362
|
+
}
|
|
3363
|
+
return false;
|
|
3364
|
+
}
|
|
3365
|
+
isDone() {
|
|
3366
|
+
return this.localData["_qg_done_at"] !== undefined;
|
|
3367
|
+
}
|
|
3368
|
+
slideQuizIsDone() {
|
|
3369
|
+
return this.localData["_q_gg_" + this.elementId + "_sa"] !== undefined;
|
|
3370
|
+
}
|
|
3371
|
+
static api = {
|
|
3372
|
+
...WidgetBase.api,
|
|
3373
|
+
initWidget: function (element, localData) {
|
|
3374
|
+
WidgetQuizGrouped.initWidgets((element, options) => new WidgetQuizGrouped(element, options), [element], localData);
|
|
3375
|
+
},
|
|
3376
|
+
/**
|
|
3377
|
+
* click on quiz answer
|
|
3378
|
+
*/
|
|
3379
|
+
select: function (element) {
|
|
3380
|
+
const widgetElement = element.closest(`.${WidgetQuizGrouped.widgetClassName}`);
|
|
3381
|
+
if (widgetElement) {
|
|
3382
|
+
const widget = WidgetQuizGrouped.getInstance(widgetElement);
|
|
3383
|
+
if (widget) {
|
|
3384
|
+
return widget.selectAnswer(element);
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
return false;
|
|
3388
|
+
},
|
|
3389
|
+
slideQuizIsDone: function (element) {
|
|
3390
|
+
const widget = WidgetQuizGrouped.getInstance(element);
|
|
3391
|
+
if (widget) {
|
|
3392
|
+
return widget.slideQuizIsDone();
|
|
3393
|
+
}
|
|
3394
|
+
return true;
|
|
3395
|
+
},
|
|
3396
|
+
};
|
|
3397
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
// Polyfill Number.isNaN(value)
|
|
3401
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
|
|
3402
|
+
Number.isNaN =
|
|
3403
|
+
Number.isNaN ||
|
|
3404
|
+
function (value) {
|
|
3405
|
+
return typeof value === "number" && value !== value;
|
|
3406
|
+
};
|
|
3407
|
+
const constants = {
|
|
3408
|
+
orientation: {
|
|
3409
|
+
horizontal: {
|
|
3410
|
+
dimension: "width",
|
|
3411
|
+
direction: "left",
|
|
3412
|
+
directionStyle: {
|
|
3413
|
+
ltr: "left",
|
|
3414
|
+
rtl: "right",
|
|
3415
|
+
},
|
|
3416
|
+
coordinate: "x",
|
|
3417
|
+
},
|
|
3418
|
+
vertical: {
|
|
3419
|
+
dimension: "height",
|
|
3420
|
+
direction: "top",
|
|
3421
|
+
directionStyle: {
|
|
3422
|
+
ltr: "bottom",
|
|
3423
|
+
rtl: "bottom",
|
|
3424
|
+
},
|
|
3425
|
+
coordinate: "y",
|
|
3426
|
+
},
|
|
3427
|
+
},
|
|
3428
|
+
};
|
|
3429
|
+
/**
|
|
3430
|
+
* Check if a `element` is visible in the DOM
|
|
3431
|
+
*
|
|
3432
|
+
* @param {Element} element
|
|
3433
|
+
* @return {Boolean}
|
|
3434
|
+
*/
|
|
3435
|
+
function isHidden(element) {
|
|
3436
|
+
return Boolean(element &&
|
|
3437
|
+
(element.offsetWidth === 0 ||
|
|
3438
|
+
element.offsetHeight === 0 ||
|
|
3439
|
+
// Also Consider native `<details>` elements.
|
|
3440
|
+
element.open === false));
|
|
3441
|
+
}
|
|
3442
|
+
/**
|
|
3443
|
+
* Get hidden parentNodes of an `element`
|
|
3444
|
+
*
|
|
3445
|
+
* @param {Element} element
|
|
3446
|
+
* @return {[type]}
|
|
3447
|
+
*/
|
|
3448
|
+
function getHiddenParentNodes(element) {
|
|
3449
|
+
var parents = [], node = element.parentNode;
|
|
3450
|
+
while (isHidden(node)) {
|
|
3451
|
+
parents.push(node);
|
|
3452
|
+
node = node.parentNode;
|
|
3453
|
+
}
|
|
3454
|
+
return parents;
|
|
3455
|
+
}
|
|
3456
|
+
/**
|
|
3457
|
+
* Returns dimensions for an element even if it is not visible in the DOM.
|
|
3458
|
+
*
|
|
3459
|
+
* @param {Element} element
|
|
3460
|
+
* @param {String} key (e.g. offsetWidth …)
|
|
3461
|
+
* @return {Number}
|
|
3462
|
+
*/
|
|
3463
|
+
function getDimension(element, key) {
|
|
3464
|
+
getHiddenParentNodes(element);
|
|
3465
|
+
// if (hiddenParentNodesLength) {
|
|
3466
|
+
// for (var i = 0; i < hiddenParentNodesLength; i++) {
|
|
3467
|
+
//
|
|
3468
|
+
// // Cache style attribute to restore it later.
|
|
3469
|
+
// inlineStyle[i] = hiddenParentNodes[i].style.cssText;
|
|
3470
|
+
//
|
|
3471
|
+
// // visually hide
|
|
3472
|
+
// if (hiddenParentNodes[i].style.setProperty) {
|
|
3473
|
+
// hiddenParentNodes[i].style.setProperty('display', 'block', 'important');
|
|
3474
|
+
// } else {
|
|
3475
|
+
// hiddenParentNodes[i].style.cssText += ';display: block !important';
|
|
3476
|
+
// }
|
|
3477
|
+
// hiddenParentNodes[i].style.height = '0';
|
|
3478
|
+
// hiddenParentNodes[i].style.overflow = 'hidden';
|
|
3479
|
+
// hiddenParentNodes[i].style.visibility = 'hidden';
|
|
3480
|
+
// toggleOpenProperty(hiddenParentNodes[i]);
|
|
3481
|
+
// }
|
|
3482
|
+
//
|
|
3483
|
+
// // Update dimension
|
|
3484
|
+
// dimension = element[key];
|
|
3485
|
+
//
|
|
3486
|
+
// for (var j = 0; j < hiddenParentNodesLength; j++) {
|
|
3487
|
+
//
|
|
3488
|
+
// // Restore the style attribute
|
|
3489
|
+
// hiddenParentNodes[j].style.cssText = inlineStyle[j];
|
|
3490
|
+
// toggleOpenProperty(hiddenParentNodes[j]);
|
|
3491
|
+
// }
|
|
3492
|
+
// }
|
|
3493
|
+
return element[key];
|
|
3494
|
+
}
|
|
3495
|
+
/**
|
|
3496
|
+
* Returns the parsed float or the default if it failed.
|
|
3497
|
+
*
|
|
3498
|
+
* @param {String} str
|
|
3499
|
+
* @param {Number} defaultValue
|
|
3500
|
+
* @return {Number}
|
|
3501
|
+
*/
|
|
3502
|
+
function tryParseFloat(str, defaultValue) {
|
|
3503
|
+
if (str == null) {
|
|
3504
|
+
return defaultValue;
|
|
3505
|
+
}
|
|
3506
|
+
var value = parseFloat(str);
|
|
3507
|
+
return Number.isNaN(value) ? defaultValue : value;
|
|
3508
|
+
}
|
|
3509
|
+
/**
|
|
3510
|
+
* Capitalize the first letter of string
|
|
3511
|
+
*
|
|
3512
|
+
* @param {String} str
|
|
3513
|
+
* @return {String}
|
|
3514
|
+
*/
|
|
3515
|
+
function ucfirst(str) {
|
|
3516
|
+
return str.charAt(0).toUpperCase() + str.substr(1);
|
|
3517
|
+
}
|
|
3518
|
+
class WidgetRangeSlider extends WidgetBase {
|
|
3519
|
+
static DEFAULTS = {
|
|
3520
|
+
slide: null,
|
|
3521
|
+
activateAfterCreate: false,
|
|
3522
|
+
create: false,
|
|
3523
|
+
localData: {},
|
|
3524
|
+
rangeClass: "slider-view",
|
|
3525
|
+
activeClass: "rangeslider--active",
|
|
3526
|
+
horizontalClass: "rangeslider--horizontal",
|
|
3527
|
+
verticalClass: "rangeslider--vertical",
|
|
3528
|
+
fillClass: "slider-fill-view",
|
|
3529
|
+
handleClass: "slider-handle-view",
|
|
3530
|
+
};
|
|
3531
|
+
static widgetClassName = "narrative-element-range-slider";
|
|
3532
|
+
label;
|
|
3533
|
+
topScale;
|
|
3534
|
+
startValue;
|
|
3535
|
+
snapPosition;
|
|
3536
|
+
hasSubmitButton;
|
|
3537
|
+
elementSlider;
|
|
3538
|
+
elementAverageResult;
|
|
3539
|
+
elementAverageResultTooltip;
|
|
3540
|
+
elementAverageResultTooltipLabelView;
|
|
3541
|
+
orientation;
|
|
3542
|
+
min;
|
|
3543
|
+
max;
|
|
3544
|
+
value;
|
|
3545
|
+
step;
|
|
3546
|
+
toFixed;
|
|
3547
|
+
fill;
|
|
3548
|
+
handle;
|
|
3549
|
+
range;
|
|
3550
|
+
DIMENSION;
|
|
3551
|
+
DIRECTION;
|
|
3552
|
+
DIRECTION_STYLE;
|
|
3553
|
+
COORDINATE;
|
|
3554
|
+
isClickCapturedBySlider = false;
|
|
3555
|
+
handleDimension;
|
|
3556
|
+
rangeDimension;
|
|
3557
|
+
maxHandlePos;
|
|
3558
|
+
grabPos;
|
|
3559
|
+
position;
|
|
3560
|
+
prevSnapValue;
|
|
3561
|
+
/**
|
|
3562
|
+
* @throws Error
|
|
3563
|
+
* @param element
|
|
3564
|
+
* @param options
|
|
3565
|
+
*/
|
|
3566
|
+
constructor(element, options) {
|
|
3567
|
+
super(element, options);
|
|
3568
|
+
this.hasSubmitButton = Boolean(this.element.querySelector(".submit-button-view"));
|
|
3569
|
+
this.topScale = this.element.querySelector(".top-scale-bar-view-group");
|
|
3570
|
+
this.snapPosition = false;
|
|
3571
|
+
try {
|
|
3572
|
+
this.snapPosition = this.topScale != null && this.topScale.getBoundingClientRect().height > 0;
|
|
3573
|
+
}
|
|
3574
|
+
catch (e) {
|
|
3575
|
+
console.error(e);
|
|
3576
|
+
}
|
|
3577
|
+
this.startValue = tryParseFloat(getTagData(this.element, "startValue"), 0);
|
|
3578
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
3579
|
+
this.elementSlider = getValueOrException(this.element.querySelector('input[type="range"]'), "Empty elementSlider");
|
|
3580
|
+
this.elementAverageResult = this.element.querySelector(".slider-average-result-view");
|
|
3581
|
+
if (this.elementAverageResult != null) {
|
|
3582
|
+
this.elementAverageResultTooltip = this.elementAverageResult.querySelector(".tooltip-view");
|
|
3583
|
+
if (this.elementAverageResultTooltip != null) {
|
|
3584
|
+
this.elementAverageResultTooltipLabelView = this.elementAverageResult.querySelector(".average-result-label-view");
|
|
3585
|
+
}
|
|
3586
|
+
}
|
|
3587
|
+
this.toFixed = (this.step + "").replace(".", "").length - 1;
|
|
3588
|
+
this.fill = getValueOrException(this.element.querySelector(`.${this.options.fillClass}`), `Empty .${this.options.fillClass}`);
|
|
3589
|
+
this.handle = getValueOrException(this.element.querySelector(`.${this.options.handleClass}`), `Empty .${this.options.handleClass}`);
|
|
3590
|
+
this.range = getValueOrException(this.element.querySelector(`.${this.options.rangeClass}`), `Empty .${this.options.rangeClass}`);
|
|
3591
|
+
this.range.id = this.id;
|
|
3592
|
+
// if (this.range.classList.contains(this.options['horizontalClass'])) {
|
|
3593
|
+
this.orientation = "horizontal";
|
|
3594
|
+
// } else if (this.range.classList.contains(this.options['verticalClass'])) {
|
|
3595
|
+
// this.orientation = 'vertical';
|
|
3596
|
+
// }
|
|
3597
|
+
this.DIMENSION = constants.orientation[this.orientation].dimension;
|
|
3598
|
+
this.DIRECTION = constants.orientation[this.orientation].direction;
|
|
3599
|
+
this.DIRECTION_STYLE = constants.orientation[this.orientation].directionStyle[this.layoutDirection];
|
|
3600
|
+
this.COORDINATE = constants.orientation[this.orientation].coordinate;
|
|
3601
|
+
// Store context
|
|
3602
|
+
this.handleDown = proxy(this.handleDown, this);
|
|
3603
|
+
this.handleMove = proxy(this.handleMove, this);
|
|
3604
|
+
this.handleEnd = proxy(this.handleEnd, this);
|
|
3605
|
+
this.refreshUserData(this.options.localData);
|
|
3606
|
+
// Attach Events
|
|
3607
|
+
// window.addEventListener('resize.' + this.identifier, debounce(function() {
|
|
3608
|
+
// // Simulate resizeEnd event.
|
|
3609
|
+
// delay(function() {
|
|
3610
|
+
// _this.update(false, false);
|
|
3611
|
+
// }, 300);
|
|
3612
|
+
// }, 20));
|
|
3613
|
+
this.env.document.addEventListener("touchstart", this.handleDown);
|
|
3614
|
+
this.env.document.addEventListener("mousedown", this.handleDown);
|
|
3615
|
+
}
|
|
3616
|
+
refreshUserData(localData) {
|
|
3617
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
3618
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
3619
|
+
if (this.localData["_rs_g_" + this.elementId + "_v"] !== undefined) {
|
|
3620
|
+
this.elementSlider.value = String(tryParseFloat(this.localData["_rs_g_" + this.elementId + "_v"], 0));
|
|
3621
|
+
this.element.classList.add("done");
|
|
3622
|
+
this.displayAverageAnswer();
|
|
3623
|
+
if (this.disableTimer) {
|
|
3624
|
+
this.showNextSlide();
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
3627
|
+
else {
|
|
3628
|
+
this.elementSlider.value = String(this.startValue);
|
|
3629
|
+
this.element.classList.remove("done");
|
|
3630
|
+
this.element.classList.remove("input-done");
|
|
3631
|
+
}
|
|
3632
|
+
this.init();
|
|
3633
|
+
}
|
|
3634
|
+
_statEventInputSave(val) {
|
|
3635
|
+
try {
|
|
3636
|
+
const labelText = this.label?.textContent ?? "";
|
|
3637
|
+
this.sendStatisticEventToApp("w-range-slider-answer", {
|
|
3638
|
+
i: this.storyId,
|
|
3639
|
+
si: this.slideIndex,
|
|
3640
|
+
wi: this.elementId,
|
|
3641
|
+
wl: labelText,
|
|
3642
|
+
wa: val,
|
|
3643
|
+
}, {
|
|
3644
|
+
story_id: this.storyId,
|
|
3645
|
+
slide_index: this.slideIndex,
|
|
3646
|
+
widget_id: this.elementId,
|
|
3647
|
+
widget_label: labelText,
|
|
3648
|
+
widget_answer: val,
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
catch (error) {
|
|
3652
|
+
console.error(error);
|
|
3653
|
+
}
|
|
3654
|
+
}
|
|
3655
|
+
click() {
|
|
3656
|
+
if (this.isDone()) {
|
|
3657
|
+
return true;
|
|
3658
|
+
}
|
|
3659
|
+
this.completeWidget();
|
|
3660
|
+
return false;
|
|
3661
|
+
}
|
|
3662
|
+
completeWidget() {
|
|
3663
|
+
if (this.widgetDone) {
|
|
3664
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
3665
|
+
setTimeout(() => {
|
|
3666
|
+
this.widgetDone?.classList.remove("active");
|
|
3667
|
+
setTimeout(() => {
|
|
3668
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
3669
|
+
}, 250);
|
|
3670
|
+
}, 2000);
|
|
3671
|
+
}
|
|
3672
|
+
this.localData["_rs_g_" + this.elementId + "_v"] = tryParseFloat(this.elementSlider.value, 0);
|
|
3673
|
+
this.localData["_rs_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
3674
|
+
// answer for question
|
|
3675
|
+
this.localData["_&ts_rs_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
3676
|
+
// hide submit button
|
|
3677
|
+
this.env.requestAnimationFrame(() => {
|
|
3678
|
+
if (this.submitButtonAnimatedView != null) {
|
|
3679
|
+
this.submitButtonAnimatedView.style.maxHeight = "0px";
|
|
3680
|
+
setTimeout(() => {
|
|
3681
|
+
// important, displayAverageAnswer need .done at element
|
|
3682
|
+
this.element.classList.add("done");
|
|
3683
|
+
this.displayAverageAnswer(true);
|
|
3684
|
+
}, 200);
|
|
3685
|
+
}
|
|
3686
|
+
else {
|
|
3687
|
+
// important, displayAverageAnswer need .done at element
|
|
3688
|
+
this.element.classList.add("done");
|
|
3689
|
+
this.displayAverageAnswer(true);
|
|
3690
|
+
}
|
|
3691
|
+
});
|
|
3692
|
+
// if (this.disableTimer) {
|
|
3693
|
+
this.showNextSlide();
|
|
3694
|
+
// }
|
|
3695
|
+
this.setLocalData(this.localData, true);
|
|
3696
|
+
this._statEventInputSave(this.localData["_rs_g_" + this.elementId + "_v"]);
|
|
3697
|
+
}
|
|
3698
|
+
isDone() {
|
|
3699
|
+
return this.localData["_rs_g_" + this.elementId + "_v"] != null;
|
|
3700
|
+
}
|
|
3701
|
+
getIsClickCapturedBySlider() {
|
|
3702
|
+
return this.isClickCapturedBySlider;
|
|
3703
|
+
}
|
|
3704
|
+
displayAverageAnswer(withTooltip = false) {
|
|
3705
|
+
let answerAllocation = {
|
|
3706
|
+
total_value: 0,
|
|
3707
|
+
total_user: 0,
|
|
3708
|
+
};
|
|
3709
|
+
let answerAllocationTs = undefined;
|
|
3710
|
+
const sharedData = this.sdkApi.getWidgetsSharedData(this.storyId, "rangeSlider" /* Widgets.RangeSlider */);
|
|
3711
|
+
if (sharedData && sharedData[this.elementId] != null && (isObject(sharedData[this.elementId]) || isArray(sharedData[this.elementId]))) {
|
|
3712
|
+
answerAllocation = sharedData[this.elementId];
|
|
3713
|
+
answerAllocationTs = sharedData.ts;
|
|
3714
|
+
}
|
|
3715
|
+
const rangeSliderDoneAt = this.localData["_rs_g_" + this.elementId + "_done_at"];
|
|
3716
|
+
if (answerAllocationTs === undefined || rangeSliderDoneAt === undefined || rangeSliderDoneAt > answerAllocationTs) {
|
|
3717
|
+
answerAllocation["total_value"] += this.localData["_rs_g_" + this.elementId + "_v"];
|
|
3718
|
+
++answerAllocation["total_user"];
|
|
3719
|
+
}
|
|
3720
|
+
let averageValue = null;
|
|
3721
|
+
if (answerAllocation["total_user"] !== undefined &&
|
|
3722
|
+
isNumber(answerAllocation["total_user"]) &&
|
|
3723
|
+
answerAllocation["total_value"] !== undefined &&
|
|
3724
|
+
isNumber(answerAllocation["total_value"])) {
|
|
3725
|
+
averageValue = Math.round((answerAllocation["total_value"] / answerAllocation["total_user"]) * 10) / 10;
|
|
3726
|
+
}
|
|
3727
|
+
if (this.elementAverageResult != null && averageValue !== null) {
|
|
3728
|
+
this.update(true, false);
|
|
3729
|
+
const positionDimension = this.env.document.documentElement.dir === "rtl" ? "right" : "left";
|
|
3730
|
+
const position = this.getPositionFromValue(averageValue) + this.handleDimension / 2;
|
|
3731
|
+
this.elementAverageResult.style[positionDimension] = position + "px";
|
|
3732
|
+
// this.elementAverageResult.style.display = 'block';
|
|
3733
|
+
if (withTooltip && this.elementAverageResultTooltipLabelView != null && this.element != null) {
|
|
3734
|
+
if (!this.elementAverageResultTooltip?.classList.contains("visible")) {
|
|
3735
|
+
this.elementAverageResultTooltip?.classList.add("visible");
|
|
3736
|
+
setTimeout(() => {
|
|
3737
|
+
if (this.elementAverageResultTooltip && this.elementAverageResultTooltip.classList) {
|
|
3738
|
+
this.elementAverageResultTooltip.classList.remove("visible");
|
|
3739
|
+
}
|
|
3740
|
+
}, 3000);
|
|
3741
|
+
}
|
|
3742
|
+
this.env.requestAnimationFrame(() => {
|
|
3743
|
+
var elementBox = this.element.getBoundingClientRect();
|
|
3744
|
+
var labelViewBox = this.elementAverageResultTooltipLabelView?.getBoundingClientRect();
|
|
3745
|
+
var offset = 0;
|
|
3746
|
+
// console.log({labelViewBox, elementBox})
|
|
3747
|
+
if (labelViewBox && labelViewBox.width !== 0) {
|
|
3748
|
+
if (labelViewBox.right > elementBox.right) {
|
|
3749
|
+
// get -x for translateX with offset to left
|
|
3750
|
+
offset = elementBox.right - labelViewBox.right;
|
|
3751
|
+
}
|
|
3752
|
+
else if (labelViewBox.left < elementBox.left) {
|
|
3753
|
+
// get +x for translateX with offset to right
|
|
3754
|
+
offset = elementBox.left - labelViewBox.left;
|
|
3755
|
+
}
|
|
3756
|
+
}
|
|
3757
|
+
if (offset !== 0) {
|
|
3758
|
+
this.elementAverageResultTooltipLabelView?.style.setProperty("transform", "translateX(" + offset + "px)");
|
|
3759
|
+
}
|
|
3760
|
+
});
|
|
3761
|
+
}
|
|
3762
|
+
}
|
|
3763
|
+
}
|
|
3764
|
+
init() {
|
|
3765
|
+
if (!this.maxHandlePos) {
|
|
3766
|
+
this.env.setTimeout(() => {
|
|
3767
|
+
this.update(true, false);
|
|
3768
|
+
}, 10);
|
|
3769
|
+
}
|
|
3770
|
+
else {
|
|
3771
|
+
this.update(true, false);
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
update(updateAttributes, triggerSlide) {
|
|
3775
|
+
updateAttributes = updateAttributes || false;
|
|
3776
|
+
if (updateAttributes) {
|
|
3777
|
+
this.min = tryParseFloat(this.elementSlider.getAttribute("min"), 0);
|
|
3778
|
+
this.max = tryParseFloat(this.elementSlider.getAttribute("max"), 100);
|
|
3779
|
+
this.value = tryParseFloat(this.elementSlider.value, Math.round(this.min + (this.max - this.min) / 2));
|
|
3780
|
+
this.step = tryParseFloat(this.elementSlider.getAttribute("step"), 1);
|
|
3781
|
+
}
|
|
3782
|
+
this.handleDimension = getDimension(this.handle, ("offset" + ucfirst(this.DIMENSION)));
|
|
3783
|
+
this.rangeDimension = getDimension(this.range, ("offset" + ucfirst(this.DIMENSION)));
|
|
3784
|
+
this.maxHandlePos = this.rangeDimension - this.handleDimension;
|
|
3785
|
+
this.grabPos = this.handleDimension / 2;
|
|
3786
|
+
this.position = this.getPositionFromValue(this.value);
|
|
3787
|
+
if (updateAttributes) {
|
|
3788
|
+
// Snapping steps
|
|
3789
|
+
this.prevSnapValue = this.getValueFromPosition(this.cap(this.position, 0, this.maxHandlePos));
|
|
3790
|
+
}
|
|
3791
|
+
this.setPosition(this.position, triggerSlide);
|
|
3792
|
+
}
|
|
3793
|
+
handleDown(e) {
|
|
3794
|
+
if (this.isDone()) {
|
|
3795
|
+
return;
|
|
3796
|
+
}
|
|
3797
|
+
let rangeslider = e.target;
|
|
3798
|
+
if (!rangeslider.classList.contains("slider-view")) {
|
|
3799
|
+
rangeslider = rangeslider.closest(".slider-view");
|
|
3800
|
+
}
|
|
3801
|
+
if (!rangeslider) {
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
if (rangeslider.id !== this.id) {
|
|
3805
|
+
return;
|
|
3806
|
+
}
|
|
3807
|
+
e.preventDefault();
|
|
3808
|
+
this.isClickCapturedBySlider = true;
|
|
3809
|
+
if (!this.maxHandlePos) {
|
|
3810
|
+
this.update(true, false);
|
|
3811
|
+
}
|
|
3812
|
+
document.addEventListener("touchmove", this.handleMove);
|
|
3813
|
+
document.addEventListener("touchend", this.handleEnd);
|
|
3814
|
+
document.addEventListener("mousemove", this.handleMove);
|
|
3815
|
+
document.addEventListener("mouseup", this.handleEnd);
|
|
3816
|
+
// add active class because Firefox is ignoring
|
|
3817
|
+
// the handle:active pseudo selector because of `e.preventDefault();`
|
|
3818
|
+
this.range.classList.add(this.options.activeClass);
|
|
3819
|
+
// If we click on the handle don't set the new position
|
|
3820
|
+
if ((" " + e.target.className + " ").replace(/[\n\t]/g, " ").indexOf(this.options.handleClass) > -1) {
|
|
3821
|
+
return;
|
|
3822
|
+
}
|
|
3823
|
+
var pos = this.getRelativePosition(e), rangePos = this.range.getBoundingClientRect()[this.DIRECTION], handlePos = this.getPositionFromNode(this.handle) - rangePos, setPos = this.orientation === "vertical" ? this.maxHandlePos - (pos - this.grabPos) : pos - this.grabPos;
|
|
3824
|
+
this.setPosition(setPos);
|
|
3825
|
+
if (pos >= handlePos && pos < handlePos + this.handleDimension) {
|
|
3826
|
+
this.grabPos = pos - handlePos;
|
|
3827
|
+
}
|
|
3828
|
+
}
|
|
3829
|
+
handleMove(e) {
|
|
3830
|
+
e.preventDefault();
|
|
3831
|
+
var pos = this.getRelativePosition(e);
|
|
3832
|
+
var setPos = this.orientation === "vertical" ? this.maxHandlePos - (pos - this.grabPos) : pos - this.grabPos;
|
|
3833
|
+
this.setPosition(setPos);
|
|
3834
|
+
}
|
|
3835
|
+
handleEnd(e) {
|
|
3836
|
+
this.env.requestAnimationFrame(() => {
|
|
3837
|
+
this.isClickCapturedBySlider = false;
|
|
3838
|
+
});
|
|
3839
|
+
// e.preventDefault();
|
|
3840
|
+
document.removeEventListener("touchmove", this.handleMove);
|
|
3841
|
+
document.removeEventListener("touchend", this.handleEnd);
|
|
3842
|
+
document.removeEventListener("mousemove", this.handleMove);
|
|
3843
|
+
document.removeEventListener("mouseup", this.handleEnd);
|
|
3844
|
+
this.range.classList.remove(this.options.activeClass);
|
|
3845
|
+
this.element.classList.add("input-done");
|
|
3846
|
+
if (!this.hasSubmitButton) {
|
|
3847
|
+
this.completeWidget();
|
|
3848
|
+
}
|
|
3849
|
+
else {
|
|
3850
|
+
this.env.requestAnimationFrame(() => {
|
|
3851
|
+
if (this.submitButtonAnimatedView != null && this.submitButtonViewHeight != null) {
|
|
3852
|
+
this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
|
|
3853
|
+
}
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3856
|
+
// Ok we're done fire the change event
|
|
3857
|
+
// this.$element.trigger('change', {origin: this.identifier});
|
|
3858
|
+
}
|
|
3859
|
+
cap = function (pos, min, max) {
|
|
3860
|
+
if (pos < min) {
|
|
3861
|
+
return min;
|
|
3862
|
+
}
|
|
3863
|
+
if (pos > max) {
|
|
3864
|
+
return max;
|
|
3865
|
+
}
|
|
3866
|
+
return pos;
|
|
3867
|
+
};
|
|
3868
|
+
setPosition(pos, triggerSlide) {
|
|
3869
|
+
var value, newPos;
|
|
3870
|
+
// Snapping steps
|
|
3871
|
+
value = this.getValueFromPosition(this.cap(pos, 0, this.maxHandlePos));
|
|
3872
|
+
newPos = this.getPositionFromValue(value);
|
|
3873
|
+
// Update ui
|
|
3874
|
+
var uiPos = newPos;
|
|
3875
|
+
// invert pos for rtl
|
|
3876
|
+
if (this.orientation === "horizontal" && this.layoutDirection === "rtl") {
|
|
3877
|
+
uiPos = this.maxHandlePos - uiPos;
|
|
3878
|
+
}
|
|
3879
|
+
// this.rangeDimension - slider width
|
|
3880
|
+
this.fill.style.transform = "translateX(" + (uiPos + this.grabPos - this.rangeDimension) + "px)";
|
|
3881
|
+
// this.fill.style[this.DIMENSION] = (uiPos + this.grabPos) + 'px';
|
|
3882
|
+
var percentage = this.getPercentageFromValue(value);
|
|
3883
|
+
// 1 + (scale - 1) * percentage
|
|
3884
|
+
this.handle.style.transform = "translateY(-50%) translateX(" + uiPos + "px) scale(calc(1 + (var(--scale-factor, 1) - 1) * " + percentage + "))";
|
|
3885
|
+
// this.handle.style[this.DIRECTION_STYLE] = uiPos + 'px';
|
|
3886
|
+
this.setValue(value);
|
|
3887
|
+
// Update globals
|
|
3888
|
+
this.position = newPos;
|
|
3889
|
+
this.value = value;
|
|
3890
|
+
if (this.snapPosition) {
|
|
3891
|
+
const stepItem = String(Math.round(this.value / this.step));
|
|
3892
|
+
this.fill.setAttribute("data-step-item", stepItem);
|
|
3893
|
+
if (this.value !== this.prevSnapValue) {
|
|
3894
|
+
this.prevSnapValue = this.value;
|
|
3895
|
+
try {
|
|
3896
|
+
this.sdkApi.vibrate(20);
|
|
3897
|
+
}
|
|
3898
|
+
catch (e) {
|
|
3899
|
+
console.error(e);
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
// Returns element position relative to the parent
|
|
3905
|
+
getPositionFromNode(node) {
|
|
3906
|
+
var i = 0;
|
|
3907
|
+
while (node !== null) {
|
|
3908
|
+
i += node.offsetLeft;
|
|
3909
|
+
node = node.offsetParent;
|
|
3910
|
+
}
|
|
3911
|
+
return i;
|
|
3912
|
+
}
|
|
3913
|
+
getRelativePosition(e) {
|
|
3914
|
+
// Get the offset DIRECTION relative to the viewport
|
|
3915
|
+
const ucCoordinate = ucfirst(this.COORDINATE);
|
|
3916
|
+
const ucCoordinateClient = `client${ucCoordinate}`;
|
|
3917
|
+
const rangePos = this.range.getBoundingClientRect()[this.DIRECTION];
|
|
3918
|
+
let pageCoordinate = 0;
|
|
3919
|
+
if (typeof e[ucCoordinateClient] !== "undefined") {
|
|
3920
|
+
pageCoordinate = e[ucCoordinateClient];
|
|
3921
|
+
}
|
|
3922
|
+
else if (e.touches && e.touches[0] && typeof e.touches[0][ucCoordinateClient] !== "undefined") {
|
|
3923
|
+
pageCoordinate = e.touches[0][ucCoordinateClient];
|
|
3924
|
+
// @ts-ignore
|
|
3925
|
+
}
|
|
3926
|
+
else if (e.currentPoint && typeof e.currentPoint[this.COORDINATE] !== "undefined") {
|
|
3927
|
+
// @ts-ignore
|
|
3928
|
+
pageCoordinate = e.currentPoint[this.COORDINATE];
|
|
3929
|
+
}
|
|
3930
|
+
return pageCoordinate - rangePos;
|
|
3931
|
+
}
|
|
3932
|
+
getPercentageFromValue(value) {
|
|
3933
|
+
var percentage;
|
|
3934
|
+
percentage = (value - this.min) / (this.max - this.min);
|
|
3935
|
+
// invert pos for rtl
|
|
3936
|
+
if (this.orientation === "horizontal" && this.layoutDirection === "rtl") {
|
|
3937
|
+
percentage = 1 - percentage;
|
|
3938
|
+
}
|
|
3939
|
+
return percentage;
|
|
3940
|
+
}
|
|
3941
|
+
getPositionFromValue(value) {
|
|
3942
|
+
var percentage, pos;
|
|
3943
|
+
percentage = (value - this.min) / (this.max - this.min);
|
|
3944
|
+
// invert pos for rtl
|
|
3945
|
+
if (this.orientation === "horizontal" && this.layoutDirection === "rtl") {
|
|
3946
|
+
percentage = 1 - percentage;
|
|
3947
|
+
}
|
|
3948
|
+
pos = !Number.isNaN(percentage) ? percentage * this.maxHandlePos : 0;
|
|
3949
|
+
return pos;
|
|
3950
|
+
}
|
|
3951
|
+
getValueFromPosition(pos) {
|
|
3952
|
+
var percentage, value;
|
|
3953
|
+
percentage = pos / (this.maxHandlePos || 1);
|
|
3954
|
+
// invert pos for rtl
|
|
3955
|
+
if (this.orientation === "horizontal" && this.layoutDirection === "rtl") {
|
|
3956
|
+
percentage = 1 - percentage;
|
|
3957
|
+
}
|
|
3958
|
+
value = this.step * Math.round((percentage * (this.max - this.min)) / this.step) + this.min;
|
|
3959
|
+
return Number(value.toFixed(this.toFixed));
|
|
3960
|
+
}
|
|
3961
|
+
setValue(value) {
|
|
3962
|
+
if (value === this.value && this.elementSlider.value !== "") {
|
|
3963
|
+
return;
|
|
3964
|
+
}
|
|
3965
|
+
// Set the new value and fire the `input` event
|
|
3966
|
+
this.elementSlider.value = String(value);
|
|
3967
|
+
// .val(value)
|
|
3968
|
+
// .trigger('input', {origin: this.identifier});
|
|
3969
|
+
}
|
|
3970
|
+
destroy() {
|
|
3971
|
+
this.env.document.removeEventListener("touchstart", this.handleDown);
|
|
3972
|
+
this.env.document.removeEventListener("mousedown", this.handleDown);
|
|
3973
|
+
// off resize event
|
|
3974
|
+
// this.$window.off('.' + this.identifier);
|
|
3975
|
+
// this.$element
|
|
3976
|
+
// .off('.' + this.identifier)
|
|
3977
|
+
// .removeAttr('style')
|
|
3978
|
+
// .removeData('plugin_' + pluginName);
|
|
3979
|
+
}
|
|
3980
|
+
static api = {
|
|
3981
|
+
...WidgetBase.api,
|
|
3982
|
+
initWidget: function (element, localData) {
|
|
3983
|
+
WidgetRangeSlider.initWidgets((element, options) => new WidgetRangeSlider(element, options), [element], localData);
|
|
3984
|
+
},
|
|
3985
|
+
click: function (element) {
|
|
3986
|
+
const widgetElement = element.closest(`.${WidgetRangeSlider.widgetClassName}`);
|
|
3987
|
+
if (widgetElement) {
|
|
3988
|
+
const widget = WidgetRangeSlider.getInstance(widgetElement);
|
|
3989
|
+
if (widget) {
|
|
3990
|
+
return widget.click();
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
return true;
|
|
3994
|
+
},
|
|
3995
|
+
isClickCapturedBySlider: function (element) {
|
|
3996
|
+
const widgetElement = element.closest(`.${WidgetRangeSlider.widgetClassName}`);
|
|
3997
|
+
if (widgetElement) {
|
|
3998
|
+
const widget = WidgetRangeSlider.getInstance(widgetElement);
|
|
3999
|
+
if (widget) {
|
|
4000
|
+
return widget.getIsClickCapturedBySlider();
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
4003
|
+
return false;
|
|
4004
|
+
},
|
|
4005
|
+
};
|
|
4006
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
4007
|
+
}
|
|
4008
|
+
|
|
4009
|
+
class WidgetRate extends WidgetBase {
|
|
4010
|
+
static DEFAULTS = {
|
|
4011
|
+
slide: null,
|
|
4012
|
+
activateAfterCreate: false,
|
|
4013
|
+
create: false,
|
|
4014
|
+
localData: {},
|
|
4015
|
+
};
|
|
4016
|
+
static widgetClassName = "narrative-element-rate";
|
|
4017
|
+
elementRect;
|
|
4018
|
+
label;
|
|
4019
|
+
nativeDialogueWasOpened = false;
|
|
4020
|
+
stars;
|
|
4021
|
+
submitToStores;
|
|
4022
|
+
submitToStoresMin;
|
|
4023
|
+
submitToStoresMax;
|
|
4024
|
+
showDialogOnLowRate;
|
|
4025
|
+
showDialogueMin;
|
|
4026
|
+
showDialogueMax;
|
|
4027
|
+
selectedStar;
|
|
4028
|
+
answerSelectDuration;
|
|
4029
|
+
constructor(element, options) {
|
|
4030
|
+
super(element, options);
|
|
4031
|
+
this.elementRect = this.element.getBoundingClientRect();
|
|
4032
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
4033
|
+
this.stars = slice.call(this.element.querySelectorAll(".input-view"));
|
|
4034
|
+
this.submitToStores = Boolean(getValueOrDefault(getTagDataAsNumber(this.element, "submitToStores"), 0));
|
|
4035
|
+
this.submitToStoresMin = getValueOrDefault(getTagDataAsNumber(this.element, "submitToStoresMin"), 4);
|
|
4036
|
+
this.submitToStoresMax = getValueOrDefault(getTagDataAsNumber(this.element, "submitToStoresMax"), 5);
|
|
4037
|
+
this.showDialogOnLowRate = Boolean(getValueOrDefault(getTagDataAsNumber(this.element, "showDialogOnLowRate"), 0));
|
|
4038
|
+
this.showDialogueMin = getValueOrDefault(getTagDataAsNumber(this.element, "showDialogueMin"), 1);
|
|
4039
|
+
this.showDialogueMax = getValueOrDefault(getTagDataAsNumber(this.element, "showDialogueMax"), 3);
|
|
4040
|
+
this.refreshUserData(this.options.localData);
|
|
4041
|
+
}
|
|
4042
|
+
refreshUserData(localData) {
|
|
4043
|
+
this.savedData = this.sdkApi.getStoryServerData(this.storyId);
|
|
4044
|
+
this.localData = extend({}, this.savedData ?? {}, localData);
|
|
4045
|
+
this.selectedStar = undefined;
|
|
4046
|
+
if (this.localData) {
|
|
4047
|
+
if (this.localData["_r_g_" + this.elementId + "_ss"] !== undefined) {
|
|
4048
|
+
this._selectStar(this.localData["_r_g_" + this.elementId + "_ss"], true);
|
|
4049
|
+
}
|
|
4050
|
+
else {
|
|
4051
|
+
this._clearSelectedStar();
|
|
4052
|
+
}
|
|
4053
|
+
}
|
|
4054
|
+
this.firstOpenTime = new Date().getTime();
|
|
4055
|
+
this.answerSelectDuration = 0;
|
|
4056
|
+
this.nativeDialogueWasOpened = false;
|
|
4057
|
+
}
|
|
4058
|
+
_statEventRateUsAnswer(answerText) {
|
|
4059
|
+
try {
|
|
4060
|
+
var labelText = this.label?.textContent ?? "";
|
|
4061
|
+
if (this.selectedStar != null) {
|
|
4062
|
+
var selectedAnswer = this.selectedStar + 1;
|
|
4063
|
+
this.sendStatisticEventToApp("w-rate-answer", {
|
|
4064
|
+
i: this.storyId,
|
|
4065
|
+
si: this.slideIndex,
|
|
4066
|
+
wi: this.elementId,
|
|
4067
|
+
wl: labelText,
|
|
4068
|
+
wa: selectedAnswer,
|
|
4069
|
+
wv: answerText,
|
|
4070
|
+
d: this.answerSelectDuration,
|
|
4071
|
+
}, {
|
|
4072
|
+
story_id: this.storyId,
|
|
4073
|
+
slide_index: this.slideIndex,
|
|
4074
|
+
widget_id: this.elementId,
|
|
4075
|
+
widget_label: labelText,
|
|
4076
|
+
widget_answer: selectedAnswer,
|
|
4077
|
+
widget_value: answerText,
|
|
4078
|
+
duration_ms: this.answerSelectDuration,
|
|
4079
|
+
});
|
|
4080
|
+
}
|
|
4081
|
+
}
|
|
4082
|
+
catch (error) {
|
|
4083
|
+
console.error(error);
|
|
4084
|
+
}
|
|
4085
|
+
}
|
|
4086
|
+
_selectStar(value, runTimer) {
|
|
4087
|
+
var list = [];
|
|
4088
|
+
var i;
|
|
4089
|
+
for (i = 0; i < this.stars.length; i++) {
|
|
4090
|
+
list[i] = this.stars[i];
|
|
4091
|
+
}
|
|
4092
|
+
forEach(list, (element, idx) => {
|
|
4093
|
+
const key = idx;
|
|
4094
|
+
if (key <= value) {
|
|
4095
|
+
element.classList.add("fill");
|
|
4096
|
+
}
|
|
4097
|
+
});
|
|
4098
|
+
if (list[value]) {
|
|
4099
|
+
list[value].classList.add("selected");
|
|
4100
|
+
}
|
|
4101
|
+
this.selectedStar = value;
|
|
4102
|
+
this.localData["_r_g_" + this.elementId + "_ss"] = value;
|
|
4103
|
+
this.element.classList.add("done");
|
|
4104
|
+
if (this.disableTimer && runTimer) {
|
|
4105
|
+
this.showNextSlide();
|
|
4106
|
+
}
|
|
4107
|
+
}
|
|
4108
|
+
_clearSelectedStar() {
|
|
4109
|
+
forEach(this.stars, function (element) {
|
|
4110
|
+
element.classList.remove("fill");
|
|
4111
|
+
element.classList.remove("selected");
|
|
4112
|
+
});
|
|
4113
|
+
this.element.classList.remove("done");
|
|
4114
|
+
}
|
|
4115
|
+
selectStar(starElement) {
|
|
4116
|
+
if (this.selectedStar !== undefined) {
|
|
4117
|
+
return true;
|
|
4118
|
+
}
|
|
4119
|
+
var index = this.stars.indexOf(starElement);
|
|
4120
|
+
this.stars.length;
|
|
4121
|
+
var value = index;
|
|
4122
|
+
// if (this.layoutDirection === 'rtl') {
|
|
4123
|
+
// value = length - index + 1;
|
|
4124
|
+
// }
|
|
4125
|
+
this.nativeDialogueWasOpened = false;
|
|
4126
|
+
if (value !== -1) {
|
|
4127
|
+
this.answerSelectDuration = new Date().getTime() - this.firstOpenTime;
|
|
4128
|
+
// 1-3 stars (default)
|
|
4129
|
+
if (value + 1 >= this.showDialogueMin && value + 1 <= this.showDialogueMax) {
|
|
4130
|
+
this.selectedStar = value;
|
|
4131
|
+
this._selectStar(this.selectedStar, false);
|
|
4132
|
+
if (this.showDialogOnLowRate) {
|
|
4133
|
+
if (this.sdkApi.isAndroid) {
|
|
4134
|
+
this.slide.classList.add("blured");
|
|
4135
|
+
}
|
|
4136
|
+
this.slide.classList.add("data-input-editing");
|
|
4137
|
+
const dataString = this.element.dataset["clientdialogwidgetconfig"];
|
|
4138
|
+
if (this.sdkApi.isExistsShowStoryTextInput && dataString) {
|
|
4139
|
+
const data = JSON.parse(dataString);
|
|
4140
|
+
data.size = getElementBounding(this.env, this.elementRect);
|
|
4141
|
+
if (!this.disableTimer) {
|
|
4142
|
+
this.sdkApi.pauseUI();
|
|
4143
|
+
}
|
|
4144
|
+
this.nativeDialogueWasOpened = true;
|
|
4145
|
+
try {
|
|
4146
|
+
data.text.value = data.text.value.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
4147
|
+
data.input.text.placeholder = data.input.text.placeholder.replaceAll("\\n", "\n").replaceAll("\\r", "\r").replaceAll("\\t", "\t");
|
|
4148
|
+
data.configV2.main.question.text.value = data.configV2.main.question.text.value
|
|
4149
|
+
.replaceAll("\\n", "\n")
|
|
4150
|
+
.replaceAll("\\r", "\r")
|
|
4151
|
+
.replaceAll("\\t", "\t");
|
|
4152
|
+
data.configV2.main.input.text.placeholder = data.configV2.main.input.text.placeholder
|
|
4153
|
+
.replaceAll("\\n", "\n")
|
|
4154
|
+
.replaceAll("\\r", "\r")
|
|
4155
|
+
.replaceAll("\\t", "\t");
|
|
4156
|
+
}
|
|
4157
|
+
catch (e) {
|
|
4158
|
+
console.error(e);
|
|
4159
|
+
}
|
|
4160
|
+
this.sdkApi.showStoryTextInput(this.id, data);
|
|
4161
|
+
}
|
|
4162
|
+
}
|
|
4163
|
+
else {
|
|
4164
|
+
this.completeWidget();
|
|
4165
|
+
this._statEventRateUsAnswer("");
|
|
4166
|
+
}
|
|
4167
|
+
return false;
|
|
4168
|
+
}
|
|
4169
|
+
else if (value + 1 >= this.submitToStoresMin && value + 1 <= this.submitToStoresMax) {
|
|
4170
|
+
var target = null;
|
|
4171
|
+
if (this.sdkApi.isAndroid) {
|
|
4172
|
+
target = getTagData(this.element, "androidLink");
|
|
4173
|
+
}
|
|
4174
|
+
else if (this.sdkApi.isIOS) {
|
|
4175
|
+
target = getTagData(this.element, "appleLink");
|
|
4176
|
+
}
|
|
4177
|
+
this._selectStar(value, false);
|
|
4178
|
+
this.completeWidget();
|
|
4179
|
+
this._statEventRateUsAnswer("");
|
|
4180
|
+
if (this.submitToStores && target) {
|
|
4181
|
+
this.sdkApi.openUrl(target);
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
else {
|
|
4185
|
+
this._selectStar(value, false);
|
|
4186
|
+
this.completeWidget();
|
|
4187
|
+
this._statEventRateUsAnswer("");
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
return false;
|
|
4191
|
+
}
|
|
4192
|
+
setUserText(text) {
|
|
4193
|
+
this.slide.classList.remove("data-input-editing");
|
|
4194
|
+
this.slide.classList.remove("blured");
|
|
4195
|
+
if (this.selectedStar != null) {
|
|
4196
|
+
this._selectStar(this.selectedStar, true);
|
|
4197
|
+
}
|
|
4198
|
+
if (!this.disableTimer && this.nativeDialogueWasOpened) {
|
|
4199
|
+
this.sdkApi.resumeUI();
|
|
4200
|
+
this.nativeDialogueWasOpened = false;
|
|
4201
|
+
}
|
|
4202
|
+
this.localData["_r_g_" + this.elementId + "_user_response"] = text;
|
|
4203
|
+
this.completeWidget();
|
|
4204
|
+
this._statEventRateUsAnswer(text);
|
|
4205
|
+
}
|
|
4206
|
+
completeWidget() {
|
|
4207
|
+
if (this.widgetDone) {
|
|
4208
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
4209
|
+
setTimeout(() => {
|
|
4210
|
+
this.widgetDone?.classList.remove("active");
|
|
4211
|
+
setTimeout(() => {
|
|
4212
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
4213
|
+
}, 250);
|
|
4214
|
+
}, 2000);
|
|
4215
|
+
}
|
|
4216
|
+
this.localData["_r_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
4217
|
+
// ответ на вопрос
|
|
4218
|
+
this.localData["_&ts_r_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
4219
|
+
this.setLocalData(this.localData, true);
|
|
4220
|
+
}
|
|
4221
|
+
isDone() {
|
|
4222
|
+
return this.localData["_r_g_" + this.elementId + "_done_at"] !== undefined;
|
|
4223
|
+
}
|
|
4224
|
+
slideRateIsDone() {
|
|
4225
|
+
return this.localData["_r_g_" + this.elementId + "_sa"] !== undefined;
|
|
4226
|
+
}
|
|
4227
|
+
static api = {
|
|
4228
|
+
...WidgetBase.api,
|
|
4229
|
+
initWidget: function (nodeList, localData) {
|
|
4230
|
+
WidgetRate.initWidgets((element, options) => new WidgetRate(element, options), slice.call(nodeList), localData);
|
|
4231
|
+
},
|
|
4232
|
+
select: function (element) {
|
|
4233
|
+
const widgetElement = element.closest(`.${WidgetRate.widgetClassName}`);
|
|
4234
|
+
if (widgetElement) {
|
|
4235
|
+
const widget = WidgetRate.getInstance(widgetElement);
|
|
4236
|
+
if (widget) {
|
|
4237
|
+
return widget.selectStar(element);
|
|
4238
|
+
}
|
|
4239
|
+
}
|
|
4240
|
+
return false;
|
|
4241
|
+
},
|
|
4242
|
+
slidePollIsDone: function (element) {
|
|
4243
|
+
const widget = WidgetRate.getInstance(element);
|
|
4244
|
+
if (widget) {
|
|
4245
|
+
return widget.slideRateIsDone();
|
|
4246
|
+
}
|
|
4247
|
+
return true;
|
|
4248
|
+
},
|
|
4249
|
+
setUserData: function (id, text) {
|
|
4250
|
+
WidgetRate.getInstanceById(id)?.setUserText(text);
|
|
4251
|
+
},
|
|
4252
|
+
};
|
|
4253
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
4254
|
+
}
|
|
4255
|
+
|
|
4256
|
+
class WidgetShare extends WidgetBase {
|
|
4257
|
+
static DEFAULTS = {
|
|
4258
|
+
slide: null,
|
|
4259
|
+
activateAfterCreate: false,
|
|
4260
|
+
create: false,
|
|
4261
|
+
localData: {},
|
|
4262
|
+
layers: [],
|
|
4263
|
+
};
|
|
4264
|
+
static widgetClassName = "narrative-element-share";
|
|
4265
|
+
layers;
|
|
4266
|
+
shareType;
|
|
4267
|
+
shareTarget;
|
|
4268
|
+
withLayer;
|
|
4269
|
+
btnDisabled;
|
|
4270
|
+
constructor(element, options) {
|
|
4271
|
+
super(element, options);
|
|
4272
|
+
this.shareType = getTagData(this.element, "shareType");
|
|
4273
|
+
this.shareTarget = getTagData(this.element, "shareTarget");
|
|
4274
|
+
this.layers = this.options.layers;
|
|
4275
|
+
this.withLayer = Boolean(getValueOrDefault(getTagDataAsNumber(this.element, "withLayer"), 0));
|
|
4276
|
+
if (this.withLayer) {
|
|
4277
|
+
if (this.isDone()) {
|
|
4278
|
+
this._showLayout(this.layers, 1);
|
|
4279
|
+
}
|
|
4280
|
+
else {
|
|
4281
|
+
this._showLayout(this.layers, 0);
|
|
4282
|
+
}
|
|
4283
|
+
}
|
|
4284
|
+
this.btnDisabled = false;
|
|
4285
|
+
// this.refreshUserData(this.options.localData);
|
|
4286
|
+
}
|
|
4287
|
+
refreshUserData(localData) { }
|
|
4288
|
+
_statEventShare(result, via) {
|
|
4289
|
+
try {
|
|
4290
|
+
var buttonText = this.element.textContent ?? "";
|
|
4291
|
+
this.sendStatisticEventToApp("w-share", {
|
|
4292
|
+
i: this.storyId,
|
|
4293
|
+
si: this.slideIndex,
|
|
4294
|
+
wi: this.elementId,
|
|
4295
|
+
wl: buttonText,
|
|
4296
|
+
wt: this.shareTarget ?? "",
|
|
4297
|
+
wa: result ? 1 : 0,
|
|
4298
|
+
wal: via ?? "",
|
|
4299
|
+
}, {
|
|
4300
|
+
story_id: this.storyId,
|
|
4301
|
+
slide_index: this.slideIndex,
|
|
4302
|
+
widget_id: this.elementId,
|
|
4303
|
+
widget_label: buttonText,
|
|
4304
|
+
widget_value: this.shareTarget ?? "",
|
|
4305
|
+
widget_answer: result ? 1 : 0,
|
|
4306
|
+
widget_answer_label: via ?? "",
|
|
4307
|
+
});
|
|
4308
|
+
}
|
|
4309
|
+
catch (error) {
|
|
4310
|
+
console.error(error);
|
|
4311
|
+
}
|
|
4312
|
+
}
|
|
4313
|
+
share() {
|
|
4314
|
+
if (!this.btnDisabled) {
|
|
4315
|
+
if (this.sdkApi.isExistsShare) {
|
|
4316
|
+
if (this.sdkApi.sdkCanSendShareComplete) {
|
|
4317
|
+
this.btnDisabled = true;
|
|
4318
|
+
}
|
|
4319
|
+
if (this.shareType === "url" || this.shareType === "story") {
|
|
4320
|
+
this.sdkApi.share(this.id, {
|
|
4321
|
+
url: this.shareTarget, // sdk old versions
|
|
4322
|
+
text: this.shareTarget,
|
|
4323
|
+
title: null,
|
|
4324
|
+
files: null,
|
|
4325
|
+
});
|
|
4326
|
+
}
|
|
4327
|
+
else if (this.shareType === "slide") {
|
|
4328
|
+
this.sdkApi.shareSlideScreenshot(this.id, "[data-element-id='" + this.elementId + "']");
|
|
4329
|
+
}
|
|
4330
|
+
}
|
|
4331
|
+
}
|
|
4332
|
+
}
|
|
4333
|
+
_complete(isSuccess) {
|
|
4334
|
+
if (!this.localData["_s_" + this.elementId + "_ts"] && isSuccess) {
|
|
4335
|
+
this.localData["_s_" + this.elementId + "_ts"] = Math.round(new Date().getTime() / 1000);
|
|
4336
|
+
// `answer_at` time
|
|
4337
|
+
this.localData["_&ts_s_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
4338
|
+
this.setLocalData(this.localData, true);
|
|
4339
|
+
}
|
|
4340
|
+
this._statEventShare(isSuccess, null);
|
|
4341
|
+
if (isSuccess && this.withLayer) {
|
|
4342
|
+
this._showLayout(this.layers, 1, true);
|
|
4343
|
+
}
|
|
4344
|
+
this.btnDisabled = false;
|
|
4345
|
+
}
|
|
4346
|
+
isDone() {
|
|
4347
|
+
return Boolean(this.localData["_s_" + this.elementId + "_ts"]);
|
|
4348
|
+
}
|
|
4349
|
+
static api = {
|
|
4350
|
+
...WidgetBase.api,
|
|
4351
|
+
// signature variants
|
|
4352
|
+
// (widget, layers, undefined) - modern web sdk
|
|
4353
|
+
// (widget, undefined, layers) - old web sdk and rn
|
|
4354
|
+
// (widget, layers, localData) - native sdk
|
|
4355
|
+
initWidget: function (nodeList, layers, localData) {
|
|
4356
|
+
if (layers === undefined && localData !== undefined) {
|
|
4357
|
+
// @ts-ignore
|
|
4358
|
+
layers = localData;
|
|
4359
|
+
localData = undefined;
|
|
4360
|
+
}
|
|
4361
|
+
WidgetShare.initWidgets((element, options) => new WidgetShare(element, { ...options, layers }), slice.call(nodeList), localData);
|
|
4362
|
+
},
|
|
4363
|
+
click: function (element) {
|
|
4364
|
+
const widgetElement = element.closest(`.${WidgetShare.widgetClassName}`);
|
|
4365
|
+
if (widgetElement) {
|
|
4366
|
+
const widget = WidgetShare.getInstance(widgetElement);
|
|
4367
|
+
if (widget) {
|
|
4368
|
+
widget.share();
|
|
4369
|
+
}
|
|
4370
|
+
}
|
|
4371
|
+
},
|
|
4372
|
+
complete: function (id, isSuccess) {
|
|
4373
|
+
WidgetShare.getInstanceById(id)?._complete(isSuccess);
|
|
4374
|
+
},
|
|
4375
|
+
};
|
|
4376
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
4377
|
+
}
|
|
4378
|
+
|
|
4379
|
+
class WidgetTest extends WidgetBase {
|
|
4380
|
+
static DEFAULTS = {
|
|
4381
|
+
slide: null,
|
|
4382
|
+
activateAfterCreate: false,
|
|
4383
|
+
create: false,
|
|
4384
|
+
localData: {},
|
|
4385
|
+
};
|
|
4386
|
+
static widgetClassName = "narrative-element-test";
|
|
4387
|
+
label;
|
|
4388
|
+
variants;
|
|
4389
|
+
testCount;
|
|
4390
|
+
selectedAnswer;
|
|
4391
|
+
withTimeToAnswer;
|
|
4392
|
+
answerTimeout;
|
|
4393
|
+
tick;
|
|
4394
|
+
cancelTick;
|
|
4395
|
+
animationFrameId;
|
|
4396
|
+
startTimerAt;
|
|
4397
|
+
timeLeft;
|
|
4398
|
+
timeLeftDefault;
|
|
4399
|
+
timeline;
|
|
4400
|
+
constructor(element, options) {
|
|
4401
|
+
super(element, options);
|
|
4402
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
4403
|
+
this.variants = slice.call(this.element.querySelectorAll(".variants-box .variant-view"));
|
|
4404
|
+
this.testCount = getValueOrException(getTagDataAsNumber(this.slide, "testCount"), "Empty testCount");
|
|
4405
|
+
this.withTimeToAnswer = Boolean(getValueOrDefault(getTagDataAsNumber(this.element, "withTimeToAnswer"), 0));
|
|
4406
|
+
this.answerTimeout = getValueOrDefault(getTagDataAsNumber(this.element, "answerTimeout"), 0);
|
|
4407
|
+
this.selectedAnswer = undefined;
|
|
4408
|
+
if (this.localData) {
|
|
4409
|
+
if (this.localData["_t_g_" + this.elementId + "_sa"] !== undefined) {
|
|
4410
|
+
this._selectAnswer(this.localData["_t_g_" + this.elementId + "_sa"]);
|
|
4411
|
+
this.setLocalData(this.localData, false);
|
|
4412
|
+
}
|
|
4413
|
+
if (this.localData["_t_fo_at"] === undefined) {
|
|
4414
|
+
this.localData["_t_fo_at"] = Math.round(new Date().getTime() / 1000);
|
|
4415
|
+
this.setLocalData(this.localData, false);
|
|
4416
|
+
}
|
|
4417
|
+
}
|
|
4418
|
+
this.firstOpenTime = new Date().getTime();
|
|
4419
|
+
this.tick = () => {
|
|
4420
|
+
this.animationFrameId = this.env.requestAnimationFrame(() => {
|
|
4421
|
+
this.tick();
|
|
4422
|
+
});
|
|
4423
|
+
// update timer
|
|
4424
|
+
// update timeline position
|
|
4425
|
+
if (this.startTimerAt) {
|
|
4426
|
+
// if (this.state.timeLeft - this.timeLeft >= 950) {
|
|
4427
|
+
// this.setState({timeLeft: this.timeLeft});
|
|
4428
|
+
// }
|
|
4429
|
+
var timeNow = new Date().getTime();
|
|
4430
|
+
this.timeLeft -= timeNow - this.startTimerAt;
|
|
4431
|
+
this.startTimerAt = timeNow;
|
|
4432
|
+
if (this.timeLeft <= 0) {
|
|
4433
|
+
this.timeLeft = 0;
|
|
4434
|
+
this.cancelTick();
|
|
4435
|
+
this.doneWithoutAnswer();
|
|
4436
|
+
}
|
|
4437
|
+
if (this.timeline) {
|
|
4438
|
+
this.timeline.style.transform = "translateX(" + String((1 - this.timeLeft / this.timeLeftDefault) * 100) + "%)";
|
|
4439
|
+
}
|
|
4440
|
+
}
|
|
4441
|
+
};
|
|
4442
|
+
this.cancelTick = () => {
|
|
4443
|
+
if (this.animationFrameId != null) {
|
|
4444
|
+
this.env.cancelAnimationFrame(this.animationFrameId);
|
|
4445
|
+
}
|
|
4446
|
+
};
|
|
4447
|
+
if (this.slideTestWithTimer()) {
|
|
4448
|
+
this.timeline = this.element.querySelector(".timeline");
|
|
4449
|
+
if (this.selectedAnswer === undefined) {
|
|
4450
|
+
// find timer element
|
|
4451
|
+
// start raf
|
|
4452
|
+
// pause raf on pauseUI (actually don`t need)
|
|
4453
|
+
this.timeLeftDefault = (this.answerTimeout ? this.answerTimeout : 0) * 1000;
|
|
4454
|
+
this.timeLeft = this.timeLeftDefault;
|
|
4455
|
+
this.animationFrameId = null;
|
|
4456
|
+
this.startTimerAt = new Date().getTime();
|
|
4457
|
+
this.tick();
|
|
4458
|
+
// set answer - unanswered (for close and run again)
|
|
4459
|
+
this.localData["_t_g_" + this.elementId + "_sa"] = -1;
|
|
4460
|
+
this.setLocalData(this.localData, true);
|
|
4461
|
+
}
|
|
4462
|
+
else {
|
|
4463
|
+
// animate 100%
|
|
4464
|
+
if (this.selectedAnswer === -1) {
|
|
4465
|
+
if (this.timeline) {
|
|
4466
|
+
this.timeline.style.transform = "translateX(100%)";
|
|
4467
|
+
}
|
|
4468
|
+
}
|
|
4469
|
+
}
|
|
4470
|
+
}
|
|
4471
|
+
// this.refreshUserData(this.options.localData);
|
|
4472
|
+
}
|
|
4473
|
+
refreshUserData(localData) { }
|
|
4474
|
+
_statEventVoteAnswer(answerScore) {
|
|
4475
|
+
try {
|
|
4476
|
+
if (this.selectedAnswer != null) {
|
|
4477
|
+
const labelText = this.label?.textContent ?? "";
|
|
4478
|
+
var answerText = "";
|
|
4479
|
+
if (this.variants[this.selectedAnswer]) {
|
|
4480
|
+
var answerLabel = this.variants[this.selectedAnswer].querySelector(".label");
|
|
4481
|
+
if (answerLabel != null) {
|
|
4482
|
+
answerText = answerLabel.textContent ?? "";
|
|
4483
|
+
}
|
|
4484
|
+
}
|
|
4485
|
+
var duration = new Date().getTime() - this.firstOpenTime;
|
|
4486
|
+
this.sendStatisticEventToApp("w-test-answer", {
|
|
4487
|
+
i: this.storyId,
|
|
4488
|
+
si: this.slideIndex,
|
|
4489
|
+
wi: this.elementId,
|
|
4490
|
+
wl: labelText,
|
|
4491
|
+
wa: this.selectedAnswer,
|
|
4492
|
+
wal: answerText,
|
|
4493
|
+
was: answerScore,
|
|
4494
|
+
d: duration,
|
|
4495
|
+
}, {
|
|
4496
|
+
story_id: this.storyId,
|
|
4497
|
+
slide_index: this.slideIndex,
|
|
4498
|
+
widget_id: this.elementId,
|
|
4499
|
+
widget_label: labelText,
|
|
4500
|
+
widget_answer: this.selectedAnswer,
|
|
4501
|
+
widget_answer_label: answerText,
|
|
4502
|
+
widget_answer_score: answerScore,
|
|
4503
|
+
duration_ms: duration,
|
|
4504
|
+
});
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
catch (error) {
|
|
4508
|
+
console.error(error);
|
|
4509
|
+
}
|
|
4510
|
+
}
|
|
4511
|
+
_selectAnswer(index) {
|
|
4512
|
+
if (this.variants[index]) {
|
|
4513
|
+
this.variants[index].classList.add("selected");
|
|
4514
|
+
}
|
|
4515
|
+
this.selectedAnswer = index;
|
|
4516
|
+
this.localData["_t_g_" + this.elementId + "_sa"] = index;
|
|
4517
|
+
this.element.classList.add("done");
|
|
4518
|
+
this.env.requestAnimationFrame(() => {
|
|
4519
|
+
if (this.submitButtonAnimatedView != null && this.submitButtonViewHeight != null) {
|
|
4520
|
+
this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
|
|
4521
|
+
}
|
|
4522
|
+
});
|
|
4523
|
+
if (this.disableTimer) {
|
|
4524
|
+
this.showNextSlide();
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
selectAnswer(answer) {
|
|
4528
|
+
if (this.selectedAnswer !== undefined) {
|
|
4529
|
+
return true;
|
|
4530
|
+
}
|
|
4531
|
+
var index = this.variants.indexOf(answer);
|
|
4532
|
+
if (index !== -1) {
|
|
4533
|
+
var answerScore = getValueOrDefault(getTagDataAsNumber(this.variants[index], "score"), 0);
|
|
4534
|
+
this._completeWidget(index, answerScore);
|
|
4535
|
+
}
|
|
4536
|
+
if (Boolean(this.withTimeToAnswer && this.answerTimeout)) {
|
|
4537
|
+
this.cancelTick();
|
|
4538
|
+
}
|
|
4539
|
+
return false;
|
|
4540
|
+
}
|
|
4541
|
+
doneWithoutAnswer() {
|
|
4542
|
+
if (this.selectedAnswer !== undefined) {
|
|
4543
|
+
return;
|
|
4544
|
+
}
|
|
4545
|
+
var index = -1, answerScore = 0;
|
|
4546
|
+
this._completeWidget(index, answerScore);
|
|
4547
|
+
}
|
|
4548
|
+
// complete answer select and save local data + stat event
|
|
4549
|
+
_completeWidget(index, answerScore) {
|
|
4550
|
+
this._selectAnswer(index);
|
|
4551
|
+
this.localData["t_score"] = (this.localData["t_score"] === undefined ? 0 : this.localData["t_score"]) + answerScore;
|
|
4552
|
+
var answeredQuestion = 0;
|
|
4553
|
+
for (var key in this.localData) {
|
|
4554
|
+
if (this.localData.hasOwnProperty(key)) {
|
|
4555
|
+
if (/^_t_g_[A-z0-9-_]+_sa$/.test(key)) {
|
|
4556
|
+
answeredQuestion++;
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
if (this.localData["_t_fa_at"] === undefined) {
|
|
4561
|
+
this.localData["_t_fa_at"] = Math.round(new Date().getTime() / 1000);
|
|
4562
|
+
}
|
|
4563
|
+
if (answeredQuestion === this.testCount) {
|
|
4564
|
+
this.localData["_t_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
4565
|
+
}
|
|
4566
|
+
// answer on question
|
|
4567
|
+
this.localData["_&ts_t_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
4568
|
+
if (this.widgetDone) {
|
|
4569
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
4570
|
+
setTimeout(() => {
|
|
4571
|
+
this.widgetDone?.classList.remove("active");
|
|
4572
|
+
setTimeout(() => {
|
|
4573
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
4574
|
+
}, 250);
|
|
4575
|
+
}, 2000);
|
|
4576
|
+
}
|
|
4577
|
+
this.setLocalData(this.localData, true);
|
|
4578
|
+
this._statEventVoteAnswer(answerScore);
|
|
4579
|
+
}
|
|
4580
|
+
isDone() {
|
|
4581
|
+
return this.localData["_t_done_at"] !== undefined && this.selectedAnswer !== undefined;
|
|
4582
|
+
}
|
|
4583
|
+
slideTestIsDone() {
|
|
4584
|
+
return this.localData["_t_g_" + this.elementId + "_sa"] !== undefined && this.selectedAnswer !== undefined;
|
|
4585
|
+
}
|
|
4586
|
+
slideTestWithTimer() {
|
|
4587
|
+
return Boolean(this.withTimeToAnswer && this.answerTimeout);
|
|
4588
|
+
}
|
|
4589
|
+
static api = {
|
|
4590
|
+
...WidgetBase.api,
|
|
4591
|
+
initWidget: function (element, localData) {
|
|
4592
|
+
WidgetTest.initWidgets((element, options) => new WidgetTest(element, options), [element], localData);
|
|
4593
|
+
},
|
|
4594
|
+
/**
|
|
4595
|
+
* click on quiz answer
|
|
4596
|
+
*/
|
|
4597
|
+
select: function (element) {
|
|
4598
|
+
const widgetElement = element.closest(`.${WidgetTest.widgetClassName}`);
|
|
4599
|
+
if (widgetElement) {
|
|
4600
|
+
const widget = WidgetTest.getInstance(widgetElement);
|
|
4601
|
+
if (widget) {
|
|
4602
|
+
return widget.selectAnswer(element);
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
return false;
|
|
4606
|
+
},
|
|
4607
|
+
slideTestIsDone: function (element) {
|
|
4608
|
+
const widget = WidgetTest.getInstance(element);
|
|
4609
|
+
if (widget) {
|
|
4610
|
+
return widget.slideTestIsDone();
|
|
4611
|
+
}
|
|
4612
|
+
return true;
|
|
4613
|
+
},
|
|
4614
|
+
slideTestWithTimer: function (element) {
|
|
4615
|
+
const widget = WidgetTest.getInstance(element);
|
|
4616
|
+
if (widget) {
|
|
4617
|
+
return widget.slideTestWithTimer();
|
|
4618
|
+
}
|
|
4619
|
+
return true;
|
|
4620
|
+
},
|
|
4621
|
+
};
|
|
4622
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
4623
|
+
}
|
|
4624
|
+
|
|
4625
|
+
class WidgetVote extends WidgetBase {
|
|
4626
|
+
static DEFAULTS = {
|
|
4627
|
+
slide: null,
|
|
4628
|
+
activateAfterCreate: false,
|
|
4629
|
+
create: false,
|
|
4630
|
+
localData: {},
|
|
4631
|
+
};
|
|
4632
|
+
static widgetClassName = "narrative-element-vote";
|
|
4633
|
+
question = null;
|
|
4634
|
+
answers = null;
|
|
4635
|
+
questionCount = null;
|
|
4636
|
+
selectedAnswer = undefined;
|
|
4637
|
+
label;
|
|
4638
|
+
variants;
|
|
4639
|
+
variantsTexts;
|
|
4640
|
+
selectedVariant;
|
|
4641
|
+
voteAllocation;
|
|
4642
|
+
hideClientTotalResult;
|
|
4643
|
+
/**
|
|
4644
|
+
* @throws Error
|
|
4645
|
+
* @param element
|
|
4646
|
+
* @param options
|
|
4647
|
+
*/
|
|
4648
|
+
constructor(element, options) {
|
|
4649
|
+
super(element, options);
|
|
4650
|
+
this.voteAllocation = getTagData(this.slide, "voteAllocation");
|
|
4651
|
+
this.label = this.element.querySelector(".label-view .label");
|
|
4652
|
+
this.variants = slice.call(this.element.querySelectorAll(".variants-box .variant-view-group"));
|
|
4653
|
+
this.variantsTexts = [];
|
|
4654
|
+
forEach(this.variants, (element, index) => {
|
|
4655
|
+
const variantView = element.querySelector(".variant-view .label");
|
|
4656
|
+
if (variantView) {
|
|
4657
|
+
this.variantsTexts.push(variantView.textContent ?? "");
|
|
4658
|
+
}
|
|
4659
|
+
});
|
|
4660
|
+
this.hideClientTotalResult = getValueOrDefault(Boolean(getTagDataAsNumber(this.element, "hideClientTotalResult")), false);
|
|
4661
|
+
this.selectedVariant = undefined;
|
|
4662
|
+
if (this.localData) {
|
|
4663
|
+
if (this.localData["_v_g_" + this.elementId + "_sa"] !== undefined) {
|
|
4664
|
+
this._selectVariant(this.localData["_v_g_" + this.elementId + "_sa"], true);
|
|
4665
|
+
}
|
|
4666
|
+
}
|
|
4667
|
+
this.firstOpenTime = new Date().getTime();
|
|
4668
|
+
// this.refreshUserData(this.options.localData);
|
|
4669
|
+
}
|
|
4670
|
+
refreshUserData(localData) { }
|
|
4671
|
+
_statEventVoteVariant() {
|
|
4672
|
+
try {
|
|
4673
|
+
if (this.selectedVariant != null) {
|
|
4674
|
+
var labelText = this.label?.textContent ?? "";
|
|
4675
|
+
var variantText = this.variantsTexts[this.selectedVariant] ? this.variantsTexts[this.selectedVariant] : "";
|
|
4676
|
+
var duration = new Date().getTime() - this.firstOpenTime;
|
|
4677
|
+
this.sendStatisticEventToApp("w-vote-answer", {
|
|
4678
|
+
i: this.storyId,
|
|
4679
|
+
si: this.slideIndex,
|
|
4680
|
+
wi: this.elementId,
|
|
4681
|
+
wl: labelText,
|
|
4682
|
+
wa: this.selectedVariant,
|
|
4683
|
+
wv: variantText,
|
|
4684
|
+
d: duration,
|
|
4685
|
+
}, {
|
|
4686
|
+
story_id: this.storyId,
|
|
4687
|
+
slide_index: this.slideIndex,
|
|
4688
|
+
widget_id: this.elementId,
|
|
4689
|
+
widget_label: labelText,
|
|
4690
|
+
widget_answer: this.selectedVariant,
|
|
4691
|
+
widget_value: variantText,
|
|
4692
|
+
duration_ms: duration,
|
|
4693
|
+
});
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
catch (error) {
|
|
4697
|
+
console.error(error);
|
|
4698
|
+
}
|
|
4699
|
+
}
|
|
4700
|
+
_selectVariant(index, filled = false) {
|
|
4701
|
+
if (this.variants[index]) {
|
|
4702
|
+
this.variants[index].classList.add("selected");
|
|
4703
|
+
}
|
|
4704
|
+
this.selectedVariant = index;
|
|
4705
|
+
this.localData["_v_g_" + this.elementId + "_sa"] = index;
|
|
4706
|
+
this.element.classList.add("done");
|
|
4707
|
+
if (filled) {
|
|
4708
|
+
this.element.classList.add("filled");
|
|
4709
|
+
}
|
|
4710
|
+
if (this.hideClientTotalResult) {
|
|
4711
|
+
const cb = () => {
|
|
4712
|
+
if (this.variants[index]) {
|
|
4713
|
+
this.variants[index].style.setProperty("--selected-variant-view-clip-area", String(0));
|
|
4714
|
+
}
|
|
4715
|
+
};
|
|
4716
|
+
if (filled) {
|
|
4717
|
+
cb();
|
|
4718
|
+
}
|
|
4719
|
+
else {
|
|
4720
|
+
this.env.requestAnimationFrame(cb);
|
|
4721
|
+
}
|
|
4722
|
+
}
|
|
4723
|
+
else {
|
|
4724
|
+
this.displayPercents(index, filled);
|
|
4725
|
+
}
|
|
4726
|
+
this.env.requestAnimationFrame(() => {
|
|
4727
|
+
if (this.submitButtonAnimatedView != null && this.submitButtonViewHeight != null) {
|
|
4728
|
+
this.submitButtonAnimatedView.style.maxHeight = this.submitButtonViewHeight + "px";
|
|
4729
|
+
}
|
|
4730
|
+
});
|
|
4731
|
+
if (this.disableTimer) {
|
|
4732
|
+
this.showNextSlide();
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
selectVariant(variant) {
|
|
4736
|
+
if (this.selectedVariant !== undefined) {
|
|
4737
|
+
return true;
|
|
4738
|
+
}
|
|
4739
|
+
var selectedVariantIndex = this.variants.indexOf(variant);
|
|
4740
|
+
if (selectedVariantIndex !== -1) {
|
|
4741
|
+
this._selectVariant(selectedVariantIndex);
|
|
4742
|
+
this.localData["_v_g_" + this.elementId + "_done_at"] = Math.round(new Date().getTime() / 1000);
|
|
4743
|
+
// ответ на вопрос
|
|
4744
|
+
this.localData["_&ts_v_g_" + this.elementId + "_a_at"] = Math.round(new Date().getTime() / 1000);
|
|
4745
|
+
if (this.widgetDone) {
|
|
4746
|
+
this.widgetDone.classList.add("active", "opacity-active");
|
|
4747
|
+
setTimeout(() => {
|
|
4748
|
+
this.widgetDone?.classList.remove("active");
|
|
4749
|
+
setTimeout(() => {
|
|
4750
|
+
this.widgetDone?.classList.remove("opacity-active");
|
|
4751
|
+
}, 250);
|
|
4752
|
+
}, 2000);
|
|
4753
|
+
}
|
|
4754
|
+
this.setLocalData(this.localData, true);
|
|
4755
|
+
this._statEventVoteVariant();
|
|
4756
|
+
}
|
|
4757
|
+
return false;
|
|
4758
|
+
}
|
|
4759
|
+
displayPercents(selectedVariantIndex, filled = false) {
|
|
4760
|
+
// voteAllocation[0] - variant total count allocation
|
|
4761
|
+
// voteAllocation[1]
|
|
4762
|
+
// ...
|
|
4763
|
+
// voteAllocation[7]
|
|
4764
|
+
let voteAllocation = [];
|
|
4765
|
+
let voteAllocationTs = undefined;
|
|
4766
|
+
const sharedData = this.sdkApi.getWidgetsSharedData(this.storyId, "vote" /* Widgets.Vote */);
|
|
4767
|
+
if (sharedData && sharedData[this.elementId] != null && (isObject(sharedData[this.elementId]) || isArray(sharedData[this.elementId]))) {
|
|
4768
|
+
voteAllocation = sharedData[this.elementId];
|
|
4769
|
+
if (isObject(sharedData[this.elementId])) {
|
|
4770
|
+
voteAllocation = slice.call(Object.values(sharedData[this.elementId]));
|
|
4771
|
+
}
|
|
4772
|
+
voteAllocationTs = sharedData.ts;
|
|
4773
|
+
}
|
|
4774
|
+
var voteDoneAt = this.localData["_v_g_" + this.elementId + "_done_at"];
|
|
4775
|
+
if (voteAllocationTs === undefined || voteDoneAt === undefined || voteDoneAt > voteAllocationTs) {
|
|
4776
|
+
forEach(this.variants, function (element, index) {
|
|
4777
|
+
const key = index;
|
|
4778
|
+
if (voteAllocation[key] === undefined || !isNumber(voteAllocation[key])) {
|
|
4779
|
+
voteAllocation[key] = 0;
|
|
4780
|
+
}
|
|
4781
|
+
if (selectedVariantIndex === key) {
|
|
4782
|
+
++voteAllocation[key];
|
|
4783
|
+
}
|
|
4784
|
+
});
|
|
4785
|
+
}
|
|
4786
|
+
// calc percents
|
|
4787
|
+
var percents = [], total = 0;
|
|
4788
|
+
forEach(this.variants, (element, index) => {
|
|
4789
|
+
const key = index;
|
|
4790
|
+
if (voteAllocation[key] !== undefined) {
|
|
4791
|
+
percents[key] = isNumber(voteAllocation[key]) ? voteAllocation[key] : parseInt(String(voteAllocation[key]));
|
|
4792
|
+
if (!isNumber(percents[key]) || isNaN(percents[key])) {
|
|
4793
|
+
percents[key] = 0;
|
|
4794
|
+
}
|
|
4795
|
+
}
|
|
4796
|
+
else {
|
|
4797
|
+
percents[key] = 0;
|
|
4798
|
+
}
|
|
4799
|
+
total += percents[key];
|
|
4800
|
+
});
|
|
4801
|
+
for (let i = 0; i < percents.length; ++i) {
|
|
4802
|
+
if (total !== 0) {
|
|
4803
|
+
percents[i] = Math.round((percents[i] / total) * 100 * 10) / 10;
|
|
4804
|
+
if (percents[i] > 100) {
|
|
4805
|
+
percents[i] = 100;
|
|
4806
|
+
}
|
|
4807
|
+
// percents[i] += '%';
|
|
4808
|
+
}
|
|
4809
|
+
}
|
|
4810
|
+
var self = this;
|
|
4811
|
+
forEach(this.variants, (element, index) => {
|
|
4812
|
+
const key = index;
|
|
4813
|
+
var percentLabels = slice.call(element.querySelectorAll(".percent-label"));
|
|
4814
|
+
forEach(percentLabels, label => {
|
|
4815
|
+
if (percents[key] != null) {
|
|
4816
|
+
label.textContent = percents[key] + "%";
|
|
4817
|
+
}
|
|
4818
|
+
});
|
|
4819
|
+
element.classList.add("selected");
|
|
4820
|
+
});
|
|
4821
|
+
var cb = function () {
|
|
4822
|
+
forEach(self.variants, function (element, index) {
|
|
4823
|
+
const key = index;
|
|
4824
|
+
if (percents[key] != null) {
|
|
4825
|
+
element.style.setProperty("--selected-variant-view-clip-area", String(100 - percents[key]));
|
|
4826
|
+
}
|
|
4827
|
+
});
|
|
4828
|
+
};
|
|
4829
|
+
if (filled) {
|
|
4830
|
+
cb();
|
|
4831
|
+
}
|
|
4832
|
+
else {
|
|
4833
|
+
this.env.requestAnimationFrame(cb);
|
|
4834
|
+
}
|
|
4835
|
+
}
|
|
4836
|
+
isDone() {
|
|
4837
|
+
return this.localData["_v_g_" + this.elementId + "_done_at"] !== undefined;
|
|
4838
|
+
}
|
|
4839
|
+
slideVoteIsDone() {
|
|
4840
|
+
return this.localData["_v_g_" + this.elementId + "_sa"] !== undefined;
|
|
4841
|
+
}
|
|
4842
|
+
static api = {
|
|
4843
|
+
...WidgetBase.api,
|
|
4844
|
+
// fix for WidgetVote on every layer of multilayers story
|
|
4845
|
+
fallbackInitOnMultiSlide: function (element, localData) {
|
|
4846
|
+
if (element.dataset.fallbackInitOnMultiSlide) {
|
|
4847
|
+
return;
|
|
4848
|
+
}
|
|
4849
|
+
var multiSlide = element.closest(".narrative-multi-slide");
|
|
4850
|
+
if (multiSlide != null) {
|
|
4851
|
+
var container = multiSlide.parentElement;
|
|
4852
|
+
var widgetElements = container?.querySelectorAll(`.${WidgetVote.widgetClassName}`);
|
|
4853
|
+
if (widgetElements != null) {
|
|
4854
|
+
for (var i = 0; i < widgetElements.length; ++i) {
|
|
4855
|
+
var widgetElement = widgetElements[i];
|
|
4856
|
+
const widget = WidgetVote.getInstance(widgetElement);
|
|
4857
|
+
if (!widget) {
|
|
4858
|
+
WidgetVote.initWidgets((element, options) => new WidgetVote(element, options), [widgetElement], localData);
|
|
4859
|
+
}
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
element.dataset.fallbackInitOnMultiSlide = "1";
|
|
4864
|
+
},
|
|
4865
|
+
initWidget: function (element, localData) {
|
|
4866
|
+
WidgetVote.initWidgets((element, options) => new WidgetVote(element, options), [element], localData).then(localData => {
|
|
4867
|
+
WidgetVote.api.fallbackInitOnMultiSlide(element, localData);
|
|
4868
|
+
});
|
|
4869
|
+
},
|
|
4870
|
+
select: function (element) {
|
|
4871
|
+
const widgetElement = element.closest(`.${WidgetVote.widgetClassName}`);
|
|
4872
|
+
if (widgetElement) {
|
|
4873
|
+
const widget = WidgetVote.getInstance(widgetElement);
|
|
4874
|
+
if (widget) {
|
|
4875
|
+
return widget.selectVariant(element);
|
|
4876
|
+
}
|
|
4877
|
+
}
|
|
4878
|
+
return false;
|
|
4879
|
+
},
|
|
4880
|
+
slideVoteIsDone: function (element) {
|
|
4881
|
+
const widget = WidgetVote.getInstance(element);
|
|
4882
|
+
if (widget) {
|
|
4883
|
+
return widget.slideVoteIsDone();
|
|
4884
|
+
}
|
|
4885
|
+
return true;
|
|
4886
|
+
},
|
|
4887
|
+
};
|
|
4888
|
+
static get [Symbol.for("___CTOR_ARGS___")]() { return [`HTMLElement`, `Partial`]; }
|
|
4889
|
+
}
|
|
4890
|
+
|
|
4891
|
+
exports.sdkInterface = void 0;
|
|
4892
|
+
const getSlideApi = (_sdkInterface) => {
|
|
4893
|
+
exports.sdkInterface = _sdkInterface;
|
|
4894
|
+
return {
|
|
4895
|
+
Animation: animationApi,
|
|
4896
|
+
WidgetCopy: WidgetCopy.api,
|
|
4897
|
+
WidgetDataInput: WidgetDataInput.api,
|
|
4898
|
+
WidgetDateCountdown: WidgetDateCountdown.api,
|
|
4899
|
+
WidgetMultiSlide: WidgetMultiSlide.api,
|
|
4900
|
+
WidgetPoll: WidgetPoll.api,
|
|
4901
|
+
WidgetPollLayers: WidgetPollLayers.api,
|
|
4902
|
+
WidgetQuest: WidgetQuest.api,
|
|
4903
|
+
WidgetQuiz: WidgetQuiz.api,
|
|
4904
|
+
WidgetQuizGrouped: WidgetQuizGrouped.api,
|
|
4905
|
+
WidgetRangeSlider: WidgetRangeSlider.api,
|
|
4906
|
+
WidgetRate: WidgetRate.api,
|
|
4907
|
+
WidgetShare: WidgetShare.api,
|
|
4908
|
+
WidgetTest: WidgetTest.api,
|
|
4909
|
+
WidgetVote: WidgetVote.api,
|
|
4910
|
+
};
|
|
4911
|
+
};
|
|
4912
|
+
|
|
4913
|
+
exports.getSlideApi = getSlideApi;
|