mixpanel-browser 2.49.0 → 2.50.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.sh +2 -1
- package/dist/mixpanel-js-wrapper.js +2 -2
- package/dist/mixpanel-recorder.js +5940 -0
- package/dist/mixpanel-recorder.min.js +24 -0
- package/dist/mixpanel.amd.js +141 -64
- package/dist/mixpanel.cjs.js +140 -63
- package/dist/mixpanel.globals.js +141 -64
- package/dist/mixpanel.min.js +110 -108
- package/dist/mixpanel.umd.js +142 -65
- package/package.json +7 -2
- package/src/config.js +1 -1
- package/src/mixpanel-core.js +53 -3
- package/src/recorder/index.js +153 -0
- package/src/recorder/rollup.config.js +19 -0
- package/src/utils.js +4 -0
package/dist/mixpanel.globals.js
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
var Config = {
|
|
5
5
|
DEBUG: false,
|
|
6
|
-
LIB_VERSION: '2.
|
|
6
|
+
LIB_VERSION: '2.50.0'
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
+
/* eslint camelcase: "off", eqeqeq: "off" */
|
|
10
|
+
|
|
9
11
|
// since es6 imports are static and we run unit tests from the console, window won't be defined when importing this file
|
|
10
|
-
var
|
|
12
|
+
var win;
|
|
11
13
|
if (typeof(window) === 'undefined') {
|
|
12
14
|
var loc = {
|
|
13
15
|
hostname: ''
|
|
14
16
|
};
|
|
15
|
-
|
|
17
|
+
win = {
|
|
16
18
|
navigator: { userAgent: '' },
|
|
17
19
|
document: {
|
|
18
20
|
location: loc,
|
|
@@ -22,32 +24,37 @@
|
|
|
22
24
|
location: loc
|
|
23
25
|
};
|
|
24
26
|
} else {
|
|
25
|
-
|
|
27
|
+
win = window;
|
|
26
28
|
}
|
|
27
29
|
|
|
30
|
+
// Maximum allowed session recording length
|
|
31
|
+
var MAX_RECORDING_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
32
|
+
|
|
28
33
|
/*
|
|
29
34
|
* Saved references to long variable names, so that closure compiler can
|
|
30
35
|
* minimize file size.
|
|
31
36
|
*/
|
|
32
37
|
|
|
33
|
-
var ArrayProto = Array.prototype
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
var
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
38
|
+
var ArrayProto = Array.prototype,
|
|
39
|
+
FuncProto = Function.prototype,
|
|
40
|
+
ObjProto = Object.prototype,
|
|
41
|
+
slice = ArrayProto.slice,
|
|
42
|
+
toString = ObjProto.toString,
|
|
43
|
+
hasOwnProperty = ObjProto.hasOwnProperty,
|
|
44
|
+
windowConsole = win.console,
|
|
45
|
+
navigator = win.navigator,
|
|
46
|
+
document$1 = win.document,
|
|
47
|
+
windowOpera = win.opera,
|
|
48
|
+
screen = win.screen,
|
|
49
|
+
userAgent = navigator.userAgent;
|
|
50
|
+
|
|
51
|
+
var nativeBind = FuncProto.bind,
|
|
52
|
+
nativeForEach = ArrayProto.forEach,
|
|
53
|
+
nativeIndexOf = ArrayProto.indexOf,
|
|
54
|
+
nativeMap = ArrayProto.map,
|
|
55
|
+
nativeIsArray = Array.isArray,
|
|
56
|
+
breaker = {};
|
|
57
|
+
|
|
51
58
|
var _ = {
|
|
52
59
|
trim: function(str) {
|
|
53
60
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim#Polyfill
|
|
@@ -837,8 +844,8 @@
|
|
|
837
844
|
var T = function() {
|
|
838
845
|
var time = 1 * new Date(); // cross-browser version of Date.now()
|
|
839
846
|
var ticks;
|
|
840
|
-
if (
|
|
841
|
-
ticks =
|
|
847
|
+
if (win.performance && win.performance.now) {
|
|
848
|
+
ticks = win.performance.now();
|
|
842
849
|
} else {
|
|
843
850
|
// fall back to busy loop
|
|
844
851
|
ticks = 0;
|
|
@@ -1624,7 +1631,7 @@
|
|
|
1624
1631
|
},
|
|
1625
1632
|
|
|
1626
1633
|
currentUrl: function() {
|
|
1627
|
-
return
|
|
1634
|
+
return win.location.href;
|
|
1628
1635
|
},
|
|
1629
1636
|
|
|
1630
1637
|
properties: function(extra_props) {
|
|
@@ -1661,10 +1668,10 @@
|
|
|
1661
1668
|
mpPageViewProperties: function() {
|
|
1662
1669
|
return _.strip_empty_properties({
|
|
1663
1670
|
'current_page_title': document$1.title,
|
|
1664
|
-
'current_domain':
|
|
1665
|
-
'current_url_path':
|
|
1666
|
-
'current_url_protocol':
|
|
1667
|
-
'current_url_search':
|
|
1671
|
+
'current_domain': win.location.hostname,
|
|
1672
|
+
'current_url_path': win.location.pathname,
|
|
1673
|
+
'current_url_protocol': win.location.protocol,
|
|
1674
|
+
'current_url_search': win.location.search
|
|
1668
1675
|
});
|
|
1669
1676
|
}
|
|
1670
1677
|
};
|
|
@@ -1702,8 +1709,7 @@
|
|
|
1702
1709
|
return matches ? matches[0] : '';
|
|
1703
1710
|
};
|
|
1704
1711
|
|
|
1705
|
-
var JSONStringify = null;
|
|
1706
|
-
var JSONParse = null;
|
|
1712
|
+
var JSONStringify = null, JSONParse = null;
|
|
1707
1713
|
if (typeof JSON !== 'undefined') {
|
|
1708
1714
|
JSONStringify = JSON.stringify;
|
|
1709
1715
|
JSONParse = JSON.parse;
|
|
@@ -1724,6 +1730,8 @@
|
|
|
1724
1730
|
_['info']['browserVersion'] = _.info.browserVersion;
|
|
1725
1731
|
_['info']['properties'] = _.info.properties;
|
|
1726
1732
|
|
|
1733
|
+
/* eslint camelcase: "off" */
|
|
1734
|
+
|
|
1727
1735
|
/**
|
|
1728
1736
|
* DomTracker Object
|
|
1729
1737
|
* @constructor
|
|
@@ -1873,8 +1881,6 @@
|
|
|
1873
1881
|
}, 0);
|
|
1874
1882
|
};
|
|
1875
1883
|
|
|
1876
|
-
// eslint-disable-line camelcase
|
|
1877
|
-
|
|
1878
1884
|
var logger$2 = console_with_prefix('lock');
|
|
1879
1885
|
|
|
1880
1886
|
/**
|
|
@@ -2021,8 +2027,6 @@
|
|
|
2021
2027
|
}
|
|
2022
2028
|
};
|
|
2023
2029
|
|
|
2024
|
-
// eslint-disable-line camelcase
|
|
2025
|
-
|
|
2026
2030
|
var logger$1 = console_with_prefix('batch');
|
|
2027
2031
|
|
|
2028
2032
|
/**
|
|
@@ -2300,8 +2304,6 @@
|
|
|
2300
2304
|
this.storage.removeItem(this.storageKey);
|
|
2301
2305
|
};
|
|
2302
2306
|
|
|
2303
|
-
// eslint-disable-line camelcase
|
|
2304
|
-
|
|
2305
2307
|
// maximum interval between request retries after exponential backoff
|
|
2306
2308
|
var MAX_RETRY_INTERVAL_MS = 10 * 60 * 1000; // 10 minutes
|
|
2307
2309
|
|
|
@@ -2596,6 +2598,19 @@
|
|
|
2596
2598
|
}
|
|
2597
2599
|
};
|
|
2598
2600
|
|
|
2601
|
+
/**
|
|
2602
|
+
* GDPR utils
|
|
2603
|
+
*
|
|
2604
|
+
* The General Data Protection Regulation (GDPR) is a regulation in EU law on data protection
|
|
2605
|
+
* and privacy for all individuals within the European Union. It addresses the export of personal
|
|
2606
|
+
* data outside the EU. The GDPR aims primarily to give control back to citizens and residents
|
|
2607
|
+
* over their personal data and to simplify the regulatory environment for international business
|
|
2608
|
+
* by unifying the regulation within the EU.
|
|
2609
|
+
*
|
|
2610
|
+
* This set of utilities is intended to enable opt in/out functionality in the Mixpanel JS SDK.
|
|
2611
|
+
* These functions are used internally by the SDK and are not intended to be publicly exposed.
|
|
2612
|
+
*/
|
|
2613
|
+
|
|
2599
2614
|
/**
|
|
2600
2615
|
* A function used to track a Mixpanel event (e.g. MixpanelLib.track)
|
|
2601
2616
|
* @callback trackFunction
|
|
@@ -2781,14 +2796,14 @@
|
|
|
2781
2796
|
if (options && options.ignoreDnt) {
|
|
2782
2797
|
return false;
|
|
2783
2798
|
}
|
|
2784
|
-
var win = (options && options.window) ||
|
|
2785
|
-
var nav = win['navigator'] || {};
|
|
2799
|
+
var win$1 = (options && options.window) || win;
|
|
2800
|
+
var nav = win$1['navigator'] || {};
|
|
2786
2801
|
var hasDntOn = false;
|
|
2787
2802
|
|
|
2788
2803
|
_.each([
|
|
2789
2804
|
nav['doNotTrack'], // standard
|
|
2790
2805
|
nav['msDoNotTrack'],
|
|
2791
|
-
win['doNotTrack']
|
|
2806
|
+
win$1['doNotTrack']
|
|
2792
2807
|
], function(dntValue) {
|
|
2793
2808
|
if (_.includes([true, 1, '1', 'yes'], dntValue)) {
|
|
2794
2809
|
hasDntOn = true;
|
|
@@ -2882,6 +2897,8 @@
|
|
|
2882
2897
|
};
|
|
2883
2898
|
}
|
|
2884
2899
|
|
|
2900
|
+
/* eslint camelcase: "off" */
|
|
2901
|
+
|
|
2885
2902
|
/** @const */ var SET_ACTION = '$set';
|
|
2886
2903
|
/** @const */ var SET_ONCE_ACTION = '$set_once';
|
|
2887
2904
|
/** @const */ var UNSET_ACTION = '$unset';
|
|
@@ -2999,6 +3016,8 @@
|
|
|
2999
3016
|
}
|
|
3000
3017
|
};
|
|
3001
3018
|
|
|
3019
|
+
/* eslint camelcase: "off" */
|
|
3020
|
+
|
|
3002
3021
|
/**
|
|
3003
3022
|
* Mixpanel Group Object
|
|
3004
3023
|
* @constructor
|
|
@@ -3167,6 +3186,8 @@
|
|
|
3167
3186
|
MixpanelGroup.prototype['unset'] = MixpanelGroup.prototype.unset;
|
|
3168
3187
|
MixpanelGroup.prototype['toString'] = MixpanelGroup.prototype.toString;
|
|
3169
3188
|
|
|
3189
|
+
/* eslint camelcase: "off" */
|
|
3190
|
+
|
|
3170
3191
|
/**
|
|
3171
3192
|
* Mixpanel People Object
|
|
3172
3193
|
* @constructor
|
|
@@ -3635,6 +3656,8 @@
|
|
|
3635
3656
|
MixpanelPeople.prototype['delete_user'] = MixpanelPeople.prototype.delete_user;
|
|
3636
3657
|
MixpanelPeople.prototype['toString'] = MixpanelPeople.prototype.toString;
|
|
3637
3658
|
|
|
3659
|
+
/* eslint camelcase: "off" */
|
|
3660
|
+
|
|
3638
3661
|
/*
|
|
3639
3662
|
* Constants
|
|
3640
3663
|
*/
|
|
@@ -4084,6 +4107,8 @@
|
|
|
4084
4107
|
return timestamp;
|
|
4085
4108
|
};
|
|
4086
4109
|
|
|
4110
|
+
/* eslint camelcase: "off" */
|
|
4111
|
+
|
|
4087
4112
|
/*
|
|
4088
4113
|
* Mixpanel JS Library
|
|
4089
4114
|
*
|
|
@@ -4130,7 +4155,7 @@
|
|
|
4130
4155
|
*/
|
|
4131
4156
|
// http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
|
|
4132
4157
|
// https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#withCredentials
|
|
4133
|
-
var USE_XHR = (
|
|
4158
|
+
var USE_XHR = (win.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest());
|
|
4134
4159
|
|
|
4135
4160
|
// IE<10 does not support cross-origin XHR's but script tags
|
|
4136
4161
|
// with defer won't block window.onload; ENQUEUE_REQUESTS
|
|
@@ -4149,7 +4174,8 @@
|
|
|
4149
4174
|
var DEFAULT_API_ROUTES = {
|
|
4150
4175
|
'track': 'track/',
|
|
4151
4176
|
'engage': 'engage/',
|
|
4152
|
-
'groups': 'groups/'
|
|
4177
|
+
'groups': 'groups/',
|
|
4178
|
+
'record': 'record/'
|
|
4153
4179
|
};
|
|
4154
4180
|
|
|
4155
4181
|
/*
|
|
@@ -4201,7 +4227,12 @@
|
|
|
4201
4227
|
'batch_flush_interval_ms': 5000,
|
|
4202
4228
|
'batch_request_timeout_ms': 90000,
|
|
4203
4229
|
'batch_autostart': true,
|
|
4204
|
-
'hooks': {}
|
|
4230
|
+
'hooks': {},
|
|
4231
|
+
'record_sessions_percent': 0,
|
|
4232
|
+
'record_idle_timeout_ms': 30 * 60 * 1000, // 30 minutes
|
|
4233
|
+
'record_max_ms': MAX_RECORDING_MS,
|
|
4234
|
+
'record_mask_text_selector': '*',
|
|
4235
|
+
'recorder_src': 'https://cdn.mxpnl.com/libs/mixpanel-recorder.min.js'
|
|
4205
4236
|
};
|
|
4206
4237
|
|
|
4207
4238
|
var DOM_LOADED = false;
|
|
@@ -4364,7 +4395,7 @@
|
|
|
4364
4395
|
});
|
|
4365
4396
|
} else {
|
|
4366
4397
|
this.init_batchers();
|
|
4367
|
-
if (sendBeacon &&
|
|
4398
|
+
if (sendBeacon && win.addEventListener) {
|
|
4368
4399
|
// Before page closes or hides (user tabs away etc), attempt to flush any events
|
|
4369
4400
|
// queued up via navigator.sendBeacon. Since sendBeacon doesn't report success/failure,
|
|
4370
4401
|
// events will not be removed from the persistent store; if the site is loaded again,
|
|
@@ -4381,12 +4412,12 @@
|
|
|
4381
4412
|
this.request_batchers.events.flush({unloading: true});
|
|
4382
4413
|
}
|
|
4383
4414
|
}, this);
|
|
4384
|
-
|
|
4415
|
+
win.addEventListener('pagehide', function(ev) {
|
|
4385
4416
|
if (ev['persisted']) {
|
|
4386
4417
|
flush_on_unload();
|
|
4387
4418
|
}
|
|
4388
4419
|
});
|
|
4389
|
-
|
|
4420
|
+
win.addEventListener('visibilitychange', function() {
|
|
4390
4421
|
if (document$1['visibilityState'] === 'hidden') {
|
|
4391
4422
|
flush_on_unload();
|
|
4392
4423
|
}
|
|
@@ -4414,6 +4445,41 @@
|
|
|
4414
4445
|
if (track_pageview_option) {
|
|
4415
4446
|
this._init_url_change_tracking(track_pageview_option);
|
|
4416
4447
|
}
|
|
4448
|
+
|
|
4449
|
+
if (this.get_config('record_sessions_percent') > 0 && Math.random() * 100 <= this.get_config('record_sessions_percent')) {
|
|
4450
|
+
this.start_session_recording();
|
|
4451
|
+
}
|
|
4452
|
+
};
|
|
4453
|
+
|
|
4454
|
+
MixpanelLib.prototype.start_session_recording = addOptOutCheckMixpanelLib(function () {
|
|
4455
|
+
if (!win['MutationObserver']) {
|
|
4456
|
+
console.critical('Browser does not support MutationObserver; skipping session recording');
|
|
4457
|
+
return;
|
|
4458
|
+
}
|
|
4459
|
+
|
|
4460
|
+
var handleLoadedRecorder = _.bind(function() {
|
|
4461
|
+
this._recorder = this._recorder || new win['__mp_recorder'](this);
|
|
4462
|
+
this._recorder['startRecording']();
|
|
4463
|
+
}, this);
|
|
4464
|
+
|
|
4465
|
+
if (_.isUndefined(win['__mp_recorder'])) {
|
|
4466
|
+
var scriptEl = document$1.createElement('script');
|
|
4467
|
+
scriptEl.type = 'text/javascript';
|
|
4468
|
+
scriptEl.async = true;
|
|
4469
|
+
scriptEl.onload = handleLoadedRecorder;
|
|
4470
|
+
scriptEl.src = this.get_config('recorder_src');
|
|
4471
|
+
document$1.head.appendChild(scriptEl);
|
|
4472
|
+
} else {
|
|
4473
|
+
handleLoadedRecorder();
|
|
4474
|
+
}
|
|
4475
|
+
});
|
|
4476
|
+
|
|
4477
|
+
MixpanelLib.prototype.stop_session_recording = function () {
|
|
4478
|
+
if (this._recorder) {
|
|
4479
|
+
this._recorder['stopRecording']();
|
|
4480
|
+
} else {
|
|
4481
|
+
console.critical('Session recorder module not loaded');
|
|
4482
|
+
}
|
|
4417
4483
|
};
|
|
4418
4484
|
|
|
4419
4485
|
// Private methods
|
|
@@ -4485,27 +4551,27 @@
|
|
|
4485
4551
|
}
|
|
4486
4552
|
|
|
4487
4553
|
if (_.include(['full-url', 'url-with-path-and-query-string', 'url-with-path'], track_pageview_option)) {
|
|
4488
|
-
|
|
4489
|
-
|
|
4554
|
+
win.addEventListener('popstate', function() {
|
|
4555
|
+
win.dispatchEvent(new Event('mp_locationchange'));
|
|
4490
4556
|
});
|
|
4491
|
-
|
|
4492
|
-
|
|
4557
|
+
win.addEventListener('hashchange', function() {
|
|
4558
|
+
win.dispatchEvent(new Event('mp_locationchange'));
|
|
4493
4559
|
});
|
|
4494
|
-
var nativePushState =
|
|
4560
|
+
var nativePushState = win.history.pushState;
|
|
4495
4561
|
if (typeof nativePushState === 'function') {
|
|
4496
|
-
|
|
4497
|
-
nativePushState.call(
|
|
4498
|
-
|
|
4562
|
+
win.history.pushState = function(state, unused, url) {
|
|
4563
|
+
nativePushState.call(win.history, state, unused, url);
|
|
4564
|
+
win.dispatchEvent(new Event('mp_locationchange'));
|
|
4499
4565
|
};
|
|
4500
4566
|
}
|
|
4501
|
-
var nativeReplaceState =
|
|
4567
|
+
var nativeReplaceState = win.history.replaceState;
|
|
4502
4568
|
if (typeof nativeReplaceState === 'function') {
|
|
4503
|
-
|
|
4504
|
-
nativeReplaceState.call(
|
|
4505
|
-
|
|
4569
|
+
win.history.replaceState = function(state, unused, url) {
|
|
4570
|
+
nativeReplaceState.call(win.history, state, unused, url);
|
|
4571
|
+
win.dispatchEvent(new Event('mp_locationchange'));
|
|
4506
4572
|
};
|
|
4507
4573
|
}
|
|
4508
|
-
|
|
4574
|
+
win.addEventListener('mp_locationchange', function() {
|
|
4509
4575
|
var current_url = _.info.currentUrl();
|
|
4510
4576
|
var should_track = false;
|
|
4511
4577
|
if (track_pageview_option === 'full-url') {
|
|
@@ -4987,6 +5053,13 @@
|
|
|
4987
5053
|
? _.info.marketingParams()
|
|
4988
5054
|
: {};
|
|
4989
5055
|
|
|
5056
|
+
if (this._recorder) {
|
|
5057
|
+
var replay_id = this._recorder['replayId'];
|
|
5058
|
+
if (replay_id) {
|
|
5059
|
+
properties['$mp_replay_id'] = replay_id;
|
|
5060
|
+
}
|
|
5061
|
+
}
|
|
5062
|
+
|
|
4990
5063
|
// note: extend writes to the first object, so lets make sure we
|
|
4991
5064
|
// don't write to the persistence properties object and info
|
|
4992
5065
|
// properties object by passing in a new object
|
|
@@ -6136,6 +6209,8 @@
|
|
|
6136
6209
|
MixpanelLib.prototype['track_with_groups'] = MixpanelLib.prototype.track_with_groups;
|
|
6137
6210
|
MixpanelLib.prototype['start_batch_senders'] = MixpanelLib.prototype.start_batch_senders;
|
|
6138
6211
|
MixpanelLib.prototype['stop_batch_senders'] = MixpanelLib.prototype.stop_batch_senders;
|
|
6212
|
+
MixpanelLib.prototype['start_session_recording'] = MixpanelLib.prototype.start_session_recording;
|
|
6213
|
+
MixpanelLib.prototype['stop_session_recording'] = MixpanelLib.prototype.stop_session_recording;
|
|
6139
6214
|
MixpanelLib.prototype['DEFAULT_API_ROUTES'] = DEFAULT_API_ROUTES;
|
|
6140
6215
|
|
|
6141
6216
|
// MixpanelPersistence Exports
|
|
@@ -6183,7 +6258,7 @@
|
|
|
6183
6258
|
|
|
6184
6259
|
mixpanel_master = instance;
|
|
6185
6260
|
if (init_type === INIT_SNIPPET) {
|
|
6186
|
-
|
|
6261
|
+
win[PRIMARY_INSTANCE_NAME] = mixpanel_master;
|
|
6187
6262
|
}
|
|
6188
6263
|
extend_mp();
|
|
6189
6264
|
}
|
|
@@ -6233,7 +6308,7 @@
|
|
|
6233
6308
|
// check to make sure we arn't in a frame
|
|
6234
6309
|
var toplevel = false;
|
|
6235
6310
|
try {
|
|
6236
|
-
toplevel =
|
|
6311
|
+
toplevel = win.frameElement === null;
|
|
6237
6312
|
} catch(e) {
|
|
6238
6313
|
// noop
|
|
6239
6314
|
}
|
|
@@ -6244,12 +6319,12 @@
|
|
|
6244
6319
|
}
|
|
6245
6320
|
|
|
6246
6321
|
// fallback handler, always will work
|
|
6247
|
-
_.register_event(
|
|
6322
|
+
_.register_event(win, 'load', dom_loaded_handler, true);
|
|
6248
6323
|
};
|
|
6249
6324
|
|
|
6250
6325
|
function init_from_snippet() {
|
|
6251
6326
|
init_type = INIT_SNIPPET;
|
|
6252
|
-
mixpanel_master =
|
|
6327
|
+
mixpanel_master = win[PRIMARY_INSTANCE_NAME];
|
|
6253
6328
|
|
|
6254
6329
|
// Initialization
|
|
6255
6330
|
if (_.isUndefined(mixpanel_master)) {
|
|
@@ -6287,6 +6362,8 @@
|
|
|
6287
6362
|
add_dom_loaded_handler();
|
|
6288
6363
|
}
|
|
6289
6364
|
|
|
6365
|
+
/* eslint camelcase: "off" */
|
|
6366
|
+
|
|
6290
6367
|
init_from_snippet();
|
|
6291
6368
|
|
|
6292
|
-
}()
|
|
6369
|
+
})();
|