@pendo/agent 2.326.0 → 2.328.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/dist/dom.esm.js +49 -47
- package/dist/pendo.module.js +1051 -418
- package/dist/pendo.module.min.js +12 -32
- package/dist/servers.json +7 -7
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -431,6 +431,7 @@ function getPolicy(pendo) {
|
|
|
431
431
|
}
|
|
432
432
|
|
|
433
433
|
var STAGING_SERVER_HASHES = 'stagingServerHashes';
|
|
434
|
+
var STAGING_DOMAINS = 'stagingDomains';
|
|
434
435
|
var pendo$1;
|
|
435
436
|
var _pendoConfig = {};
|
|
436
437
|
function loadAsModule(config) {
|
|
@@ -523,6 +524,27 @@ function urlMatchesPatterns(url, patterns = [], hashes = []) {
|
|
|
523
524
|
}
|
|
524
525
|
return false;
|
|
525
526
|
}
|
|
527
|
+
function domainSuffixes(host) {
|
|
528
|
+
var hostname = (host || '').split(':')[0].toLowerCase();
|
|
529
|
+
if (!hostname || /^[\d.]+$/.test(hostname) || hostname.indexOf(':') >= 0)
|
|
530
|
+
return [];
|
|
531
|
+
var labels = hostname.split('.');
|
|
532
|
+
var suffixes = [];
|
|
533
|
+
for (var i = 0; i <= labels.length - 2; i++) {
|
|
534
|
+
suffixes.push(labels.slice(i).join('.'));
|
|
535
|
+
}
|
|
536
|
+
return suffixes;
|
|
537
|
+
}
|
|
538
|
+
function hostMatchesStagingDomains(host, domains = []) {
|
|
539
|
+
if (!domains.length)
|
|
540
|
+
return false;
|
|
541
|
+
var suffixes = domainSuffixes(host);
|
|
542
|
+
for (var i = 0; i < suffixes.length; i++) {
|
|
543
|
+
if (domains.indexOf(getHash(suffixes[i])) >= 0)
|
|
544
|
+
return true;
|
|
545
|
+
}
|
|
546
|
+
return false;
|
|
547
|
+
}
|
|
526
548
|
function isStagingServer(config, location) {
|
|
527
549
|
if (!config) {
|
|
528
550
|
config = getPendoConfig();
|
|
@@ -536,7 +558,8 @@ function isStagingServer(config, location) {
|
|
|
536
558
|
if (!location) {
|
|
537
559
|
location = window.location;
|
|
538
560
|
}
|
|
539
|
-
return urlMatchesPatterns(location.host, config.stagingServers, config[STAGING_SERVER_HASHES])
|
|
561
|
+
return urlMatchesPatterns(location.host, config.stagingServers, config[STAGING_SERVER_HASHES]) ||
|
|
562
|
+
hostMatchesStagingDomains(location.host, config[STAGING_DOMAINS]);
|
|
540
563
|
}
|
|
541
564
|
function getHash(str) {
|
|
542
565
|
return b64.uint8ToBase64(sha1
|
|
@@ -2707,11 +2730,11 @@ var underscoreExports = underscore.exports;
|
|
|
2707
2730
|
var _ = /*@__PURE__*/getDefaultExportFromCjs(underscoreExports);
|
|
2708
2731
|
|
|
2709
2732
|
/**
|
|
2710
|
-
* Utility function to check if passed value exists. Returns false for `null` and `undefined`.
|
|
2733
|
+
* Utility function to check if the passed value exists. Returns false for `null` and `undefined`.
|
|
2711
2734
|
*
|
|
2712
2735
|
* @access public
|
|
2713
2736
|
* @category Utility
|
|
2714
|
-
* @param {any} value
|
|
2737
|
+
* @param {any} arg value to type check
|
|
2715
2738
|
* @returns {Boolean}
|
|
2716
2739
|
* @example
|
|
2717
2740
|
* pendo.doesExist(null) => false
|
|
@@ -2964,7 +2987,7 @@ var ConfigReader = (function () {
|
|
|
2964
2987
|
*
|
|
2965
2988
|
* @access public
|
|
2966
2989
|
* @category Config/Core
|
|
2967
|
-
* @name
|
|
2990
|
+
* @name forcedLeader
|
|
2968
2991
|
* @default false
|
|
2969
2992
|
* @type {boolean}
|
|
2970
2993
|
*/
|
|
@@ -3151,7 +3174,7 @@ var ConfigReader = (function () {
|
|
|
3151
3174
|
* An array of exact strings that can still be included in event data if text capture is disabled
|
|
3152
3175
|
* (`excludeAllText`). This will not override any allow list specified by your application settings but will apply if none is provided.
|
|
3153
3176
|
* These are not selectors but are equality checks (the string 'Bug' will allow links that have 'Bug' as the
|
|
3154
|
-
* text to be captured but not ones like 'Bug Report')
|
|
3177
|
+
* text to be captured but not ones like 'Bug Report').
|
|
3155
3178
|
*
|
|
3156
3179
|
* @access public
|
|
3157
3180
|
* @category Config/Analytics
|
|
@@ -3249,7 +3272,7 @@ var ConfigReader = (function () {
|
|
|
3249
3272
|
/**
|
|
3250
3273
|
* By default, the web SDK will also attempt to intercept calls to `stopPropagation` and
|
|
3251
3274
|
* `stopImmediatePropagation` for click, focus, submit, and change events in order to ensure that Pendo can
|
|
3252
|
-
* still
|
|
3275
|
+
* still properly recognize these events. In the case of this causing duplicate events or other issues, this
|
|
3253
3276
|
* functionality can be disabled.
|
|
3254
3277
|
*
|
|
3255
3278
|
* @access public
|
|
@@ -3312,7 +3335,7 @@ var ConfigReader = (function () {
|
|
|
3312
3335
|
*/
|
|
3313
3336
|
addOption('cacheGuides', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3314
3337
|
/**
|
|
3315
|
-
* How often to clear the guides cache (in milliseconds)
|
|
3338
|
+
* How often to clear the guides cache (in milliseconds).
|
|
3316
3339
|
*
|
|
3317
3340
|
* @access public
|
|
3318
3341
|
* @category Config/Guides
|
|
@@ -3346,7 +3369,7 @@ var ConfigReader = (function () {
|
|
|
3346
3369
|
addOption('disableGlobalCSS', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3347
3370
|
/**
|
|
3348
3371
|
* Building block guides use an inline style tag for various pseudo styles (e.g. hover, carets, animations).
|
|
3349
|
-
* These can be turned off using this flag for
|
|
3372
|
+
* These can be turned off using this flag for applications with more restrictive CSP settings but will
|
|
3350
3373
|
* require custom effort to reach style parity.
|
|
3351
3374
|
*
|
|
3352
3375
|
* @access public
|
|
@@ -3372,7 +3395,7 @@ var ConfigReader = (function () {
|
|
|
3372
3395
|
* cookies, localStorage, click tracking, and metadata. Only displays guides
|
|
3373
3396
|
* that have been configured explicitly to show to this visitor.
|
|
3374
3397
|
*
|
|
3375
|
-
* @access
|
|
3398
|
+
* @access private
|
|
3376
3399
|
* @category Config/Guides
|
|
3377
3400
|
* @name doNotTrackGuides
|
|
3378
3401
|
* @default false
|
|
@@ -3380,7 +3403,7 @@ var ConfigReader = (function () {
|
|
|
3380
3403
|
*/
|
|
3381
3404
|
addOption('doNotTrackGuides', [SNIPPET_SRC, PENDO_CONFIG_SRC]);
|
|
3382
3405
|
/**
|
|
3383
|
-
* If `true`, the web SDK will listen for `alt+shift+8` on the keyboard and try to launch the designer
|
|
3406
|
+
* If `true`, the web SDK will listen for `alt+shift+8` on the keyboard and try to launch the designer. The
|
|
3384
3407
|
* keyboard shortcut requires the guide launch modal of Engage to be open in another tab showing the shortcut.
|
|
3385
3408
|
*
|
|
3386
3409
|
* @access public
|
|
@@ -3458,7 +3481,7 @@ var ConfigReader = (function () {
|
|
|
3458
3481
|
*/
|
|
3459
3482
|
addOption('guides.disabled', [SNIPPET_SRC], false, undefined, ['disableGuides']);
|
|
3460
3483
|
/**
|
|
3461
|
-
* If
|
|
3484
|
+
* If `true`, guides with slow selectors will be removed from guide display processing.
|
|
3462
3485
|
* This will improve application performance, but slow guides will not be shown to users.
|
|
3463
3486
|
*
|
|
3464
3487
|
* @access public
|
|
@@ -3514,7 +3537,7 @@ var ConfigReader = (function () {
|
|
|
3514
3537
|
*/
|
|
3515
3538
|
addOption('inlineStyleNonce', [SNIPPET_SRC]);
|
|
3516
3539
|
/**
|
|
3517
|
-
* Formerly `leaderKey
|
|
3540
|
+
* Formerly `leaderKey`. Specify a preferred publicAppId to lead the multi-application iframe installation to make decisions about automatic
|
|
3518
3541
|
* guide display. In installations with more than 2 publicAppIds, the leaderApplication can be specified as a priority
|
|
3519
3542
|
* list (e.g. `leaderApplication: ['key1', 'key2', ...]`). Either all frames must agree on the leaderApplication setting,
|
|
3520
3543
|
* or only one frame should specify the leaderApplication. If neither of these conditions are met, the default leader
|
|
@@ -3544,7 +3567,7 @@ var ConfigReader = (function () {
|
|
|
3544
3567
|
addOption('storage.allowKeys', [SNIPPET_SRC], '*');
|
|
3545
3568
|
// Feedback
|
|
3546
3569
|
/**
|
|
3547
|
-
* If Feedback is
|
|
3570
|
+
* If Feedback is set up for your subscription, this option can be used to selectively disable Feedback.
|
|
3548
3571
|
*
|
|
3549
3572
|
* @access public
|
|
3550
3573
|
* @category Config/Core
|
|
@@ -3557,8 +3580,8 @@ var ConfigReader = (function () {
|
|
|
3557
3580
|
addOption('feedbackSettings', [PENDO_CONFIG_SRC], {});
|
|
3558
3581
|
addOption('pendoFeedback', [PENDO_CONFIG_SRC], false);
|
|
3559
3582
|
/**
|
|
3560
|
-
* If set, the web SDK will use this as the suffix when writing last step advanced key into the
|
|
3561
|
-
* This supports cross
|
|
3583
|
+
* If set, the web SDK will use this as the suffix when writing the last step advanced key into the visitor's cookie.
|
|
3584
|
+
* This supports cross-app guides by having a shared accessible location for different apps on the same effective level domain.
|
|
3562
3585
|
*
|
|
3563
3586
|
* @access public
|
|
3564
3587
|
* @category Config/Core
|
|
@@ -3979,12 +4002,12 @@ let SERVER = '';
|
|
|
3979
4002
|
let ASSET_HOST = '';
|
|
3980
4003
|
let ASSET_PATH = '';
|
|
3981
4004
|
let DESIGNER_SERVER = '';
|
|
3982
|
-
let VERSION = '2.
|
|
3983
|
-
let PACKAGE_VERSION = '2.
|
|
4005
|
+
let VERSION = '2.328.0_';
|
|
4006
|
+
let PACKAGE_VERSION = '2.328.0';
|
|
3984
4007
|
let LOADER = 'xhr';
|
|
3985
4008
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
3986
4009
|
/**
|
|
3987
|
-
* Returns current version of the Pendo Web SDK as a string. Also directly accessible at `pendo.VERSION`.
|
|
4010
|
+
* Returns the current version of the Pendo Web SDK as a string. Also directly accessible at `pendo.VERSION`.
|
|
3988
4011
|
*
|
|
3989
4012
|
* @access public
|
|
3990
4013
|
* @category Core
|
|
@@ -5658,6 +5681,7 @@ var Events = (function () {
|
|
|
5658
5681
|
new EventType('segmentFlagsReady', [DEBUG, LIFECYCLE]),
|
|
5659
5682
|
new EventType('segmentFlagsError', [DEBUG, LIFECYCLE]),
|
|
5660
5683
|
new EventType('guideListChanged', [DEBUG, LIFECYCLE]),
|
|
5684
|
+
new EventType('guidesReceived', [DEBUG, LIFECYCLE]),
|
|
5661
5685
|
new EventType('guideSeen', [DEBUG, LIFECYCLE]),
|
|
5662
5686
|
new EventType('guideNotSeen', [DEBUG, LIFECYCLE]),
|
|
5663
5687
|
new EventType('guideAdvanced', [DEBUG, LIFECYCLE]),
|
|
@@ -5925,7 +5949,7 @@ const ACCOUNT_ID_KEY = 'accountId';
|
|
|
5925
5949
|
*
|
|
5926
5950
|
* @access public
|
|
5927
5951
|
* @category Identity
|
|
5928
|
-
* @param {string} prefix string to prepend to the unique id
|
|
5952
|
+
* @param {string} [prefix] string to prepend to the unique id
|
|
5929
5953
|
* @returns {string}
|
|
5930
5954
|
* @example
|
|
5931
5955
|
* pendo.generate_unique_id('user-') => 'user-RaPiWJ5M53Y'
|
|
@@ -6042,7 +6066,7 @@ function findVisitorId() {
|
|
|
6042
6066
|
}
|
|
6043
6067
|
/**
|
|
6044
6068
|
* Returns the id for the visitor currently being applied to any events being sent to Pendo.
|
|
6045
|
-
* Will always be set either by host application or as an anonymous generated ID.
|
|
6069
|
+
* Will always be set either by the host application or as an anonymous generated ID.
|
|
6046
6070
|
*
|
|
6047
6071
|
* @access public
|
|
6048
6072
|
* @alias getVisitorId
|
|
@@ -6072,8 +6096,8 @@ function get_visitor_id_public() {
|
|
|
6072
6096
|
return get_visitor_id() || generate_anonymous_visitor_id();
|
|
6073
6097
|
}
|
|
6074
6098
|
/**
|
|
6075
|
-
* Sets visitor id for the web SDK. Requires a valid visitor id string. This will not change
|
|
6076
|
-
* or clear existing visitor metadata
|
|
6099
|
+
* Sets the visitor id for the web SDK. Requires a valid visitor id string. This will not change
|
|
6100
|
+
* or clear existing visitor metadata.
|
|
6077
6101
|
*
|
|
6078
6102
|
* @access public
|
|
6079
6103
|
* @category Identity
|
|
@@ -6115,8 +6139,8 @@ var get_account_id = function () {
|
|
|
6115
6139
|
return pendo$1.accountId;
|
|
6116
6140
|
};
|
|
6117
6141
|
/**
|
|
6118
|
-
* Sets account id for the web SDK without changing existing metadata. However,
|
|
6119
|
-
*
|
|
6142
|
+
* Sets the account id for the web SDK without changing existing metadata. However,
|
|
6143
|
+
* an invalid account id or an explicit `null` value will clear the current account id
|
|
6120
6144
|
* and account metadata.
|
|
6121
6145
|
*
|
|
6122
6146
|
* @access public
|
|
@@ -6167,7 +6191,7 @@ function clearAccount() {
|
|
|
6167
6191
|
}
|
|
6168
6192
|
}
|
|
6169
6193
|
/**
|
|
6170
|
-
* Removes current visitor id and account id. Triggers an identify event and reloads
|
|
6194
|
+
* Removes the current visitor id and account id. Triggers an identify event and reloads
|
|
6171
6195
|
* with a new anonymous visitor.
|
|
6172
6196
|
*
|
|
6173
6197
|
* @access public
|
|
@@ -8902,16 +8926,17 @@ var SizzleProxy = wrapSizzle(Sizzle);
|
|
|
8902
8926
|
* pendo.dom('h1')[0].remove()
|
|
8903
8927
|
* @example
|
|
8904
8928
|
* pendo.dom('.left').css({ 'text-align': 'center' })
|
|
8905
|
-
*/
|
|
8906
|
-
|
|
8907
|
-
*
|
|
8908
|
-
*
|
|
8909
|
-
* @
|
|
8910
|
-
* @
|
|
8911
|
-
* @
|
|
8912
|
-
* @
|
|
8913
|
-
*
|
|
8914
|
-
|
|
8929
|
+
*/
|
|
8930
|
+
/**
|
|
8931
|
+
* Creates new DOM elements from HTML text.
|
|
8932
|
+
*
|
|
8933
|
+
* @param {string} htmlString HTML syntax used to produce new DOM elements
|
|
8934
|
+
* @returns {DomQuery} array with the newly created elements
|
|
8935
|
+
* @access public
|
|
8936
|
+
* @category DOM
|
|
8937
|
+
* @example
|
|
8938
|
+
* pendo.dom('<div><span>this should create an unattached DOM node</span></div>');
|
|
8939
|
+
*/
|
|
8915
8940
|
function dom(selection, context) {
|
|
8916
8941
|
var self = this;
|
|
8917
8942
|
var nodes;
|
|
@@ -9673,7 +9698,7 @@ var objectToQueryString = function (obj) {
|
|
|
9673
9698
|
}, '');
|
|
9674
9699
|
};
|
|
9675
9700
|
/**
|
|
9676
|
-
* URL getter that
|
|
9701
|
+
* URL getter that returns the URL used by the web SDK to describe all data events
|
|
9677
9702
|
* collected for this app and for Guide requests. This URL can differ from the browser's URL based on
|
|
9678
9703
|
* customizations made by the host application. The URL customizations can be learned about [here](https://agent.pendo.io/advanced/location).
|
|
9679
9704
|
*
|
|
@@ -10108,7 +10133,7 @@ var locked = false;
|
|
|
10108
10133
|
* @category Events
|
|
10109
10134
|
* @example
|
|
10110
10135
|
* $ pendo.stopSendingEvents()
|
|
10111
|
-
* > Pendo Web SDK locked.
|
|
10136
|
+
* > Pendo Web SDK locked. No more events will be written.
|
|
10112
10137
|
*/
|
|
10113
10138
|
var lockEvents = function () {
|
|
10114
10139
|
var fireEvent = isUnlocked();
|
|
@@ -10125,7 +10150,7 @@ var lockEvents = function () {
|
|
|
10125
10150
|
* @category Events
|
|
10126
10151
|
* @example
|
|
10127
10152
|
* $ pendo.startSendingEvents()
|
|
10128
|
-
* > Pendo Web SDK unlocked.
|
|
10153
|
+
* > Pendo Web SDK unlocked. Events will be written.
|
|
10129
10154
|
*/
|
|
10130
10155
|
var unlockEvents = function () {
|
|
10131
10156
|
var fireEvent = !isUnlocked();
|
|
@@ -10155,8 +10180,8 @@ var isUnlocked = function () {
|
|
|
10155
10180
|
* Check if the Element has this classname.
|
|
10156
10181
|
*
|
|
10157
10182
|
* @alias hasClass
|
|
10158
|
-
* @param {element}
|
|
10159
|
-
* @param {String}
|
|
10183
|
+
* @param {element} ele The Element to test for the classname
|
|
10184
|
+
* @param {String} cls The classname to look for on the element
|
|
10160
10185
|
* @returns {Boolean}
|
|
10161
10186
|
* @access public
|
|
10162
10187
|
* @category DOM
|
|
@@ -10196,7 +10221,7 @@ var _addClass = function (ele, cls) {
|
|
|
10196
10221
|
}
|
|
10197
10222
|
};
|
|
10198
10223
|
/**
|
|
10199
|
-
* Remove a classname from an
|
|
10224
|
+
* Remove a classname from an Element's classlist.
|
|
10200
10225
|
*
|
|
10201
10226
|
* @alias removeClass
|
|
10202
10227
|
* @param {element} ele The Element from which the class will be removed
|
|
@@ -10219,7 +10244,7 @@ var _removeClass = function (ele, cls) {
|
|
|
10219
10244
|
}
|
|
10220
10245
|
};
|
|
10221
10246
|
/**
|
|
10222
|
-
* Sets the classname
|
|
10247
|
+
* Sets the classname for an Element.
|
|
10223
10248
|
*
|
|
10224
10249
|
* @alias setClass
|
|
10225
10250
|
* @param {element} ele The Element that will get the new classlist.
|
|
@@ -11031,8 +11056,8 @@ DomQuery.$ = {
|
|
|
11031
11056
|
return newDom;
|
|
11032
11057
|
},
|
|
11033
11058
|
/**
|
|
11034
|
-
* Iterate over each element in the DomQuery list and call the
|
|
11035
|
-
*
|
|
11059
|
+
* Iterate over each element in the DomQuery list and call the provided callback function passing in the
|
|
11060
|
+
* element as the argument.
|
|
11036
11061
|
*
|
|
11037
11062
|
* @function each
|
|
11038
11063
|
* @param {function} callback The callback to be called for each element in the list
|
|
@@ -11054,7 +11079,7 @@ DomQuery.$ = {
|
|
|
11054
11079
|
* Iterate over each element in the DomQuery list and create and append the Elements represented by the HTML string provided.
|
|
11055
11080
|
*
|
|
11056
11081
|
* @function html
|
|
11057
|
-
* @param {String}
|
|
11082
|
+
* @param {String} content String representing html to be created as dom Elements for each of the Elements in the list.
|
|
11058
11083
|
* @returns {DomQuery}
|
|
11059
11084
|
* @category DOMQuery
|
|
11060
11085
|
* @access public
|
|
@@ -11075,7 +11100,7 @@ DomQuery.$ = {
|
|
|
11075
11100
|
* Iterate over each element in the DomQuery list and add the text provided as innerText on the element.
|
|
11076
11101
|
*
|
|
11077
11102
|
* @function text
|
|
11078
|
-
* @param {String} content String to be added as innerText
|
|
11103
|
+
* @param {String} content String to be added as innerText.
|
|
11079
11104
|
* @returns {DomQuery}
|
|
11080
11105
|
* @access public
|
|
11081
11106
|
* @category DOMQuery
|
|
@@ -11140,7 +11165,7 @@ DomQuery.$ = {
|
|
|
11140
11165
|
});
|
|
11141
11166
|
},
|
|
11142
11167
|
/**
|
|
11143
|
-
* Iterate over each element and
|
|
11168
|
+
* Iterate over each element and check for each class name. Returns true if all elements have each classname.
|
|
11144
11169
|
*
|
|
11145
11170
|
* @function hasClass
|
|
11146
11171
|
* @param {String} classNames Space separated string of classnames.
|
|
@@ -11163,7 +11188,7 @@ DomQuery.$ = {
|
|
|
11163
11188
|
return allElemsHaveClass;
|
|
11164
11189
|
},
|
|
11165
11190
|
/**
|
|
11166
|
-
* Iterate over each element and toggle each class name on or off depending on
|
|
11191
|
+
* Iterate over each element and toggle each class name on or off depending on
|
|
11167
11192
|
* the current state of the element.
|
|
11168
11193
|
*
|
|
11169
11194
|
* @function toggleClass
|
|
@@ -11191,7 +11216,7 @@ DomQuery.$ = {
|
|
|
11191
11216
|
* Iterate over each element and apply the styles object.
|
|
11192
11217
|
*
|
|
11193
11218
|
* @function css
|
|
11194
|
-
* @param {Object} styles Object containing style
|
|
11219
|
+
* @param {Object} styles Object containing style attribute names and values.
|
|
11195
11220
|
* @returns {DomQuery}
|
|
11196
11221
|
* @access public
|
|
11197
11222
|
* @category DOMQuery
|
|
@@ -11245,7 +11270,7 @@ DomQuery.$ = {
|
|
|
11245
11270
|
return self;
|
|
11246
11271
|
},
|
|
11247
11272
|
/**
|
|
11248
|
-
* Add all elements in the list as
|
|
11273
|
+
* Add all elements in the list as topmost child nodes of the first element found for the given selector.
|
|
11249
11274
|
*
|
|
11250
11275
|
* @function prependTo
|
|
11251
11276
|
* @param {String} selector CSS selector to identify the target parent element
|
|
@@ -11260,10 +11285,10 @@ DomQuery.$ = {
|
|
|
11260
11285
|
return this;
|
|
11261
11286
|
},
|
|
11262
11287
|
/**
|
|
11263
|
-
* Add all children from the selector as
|
|
11288
|
+
* Add all children from the selector as topmost children of the first element in this list.
|
|
11264
11289
|
*
|
|
11265
11290
|
* @function prepend
|
|
11266
|
-
* @param {String} selector CSS selector to identify
|
|
11291
|
+
* @param {String} selector CSS selector to identify topmost child element(s)
|
|
11267
11292
|
* @returns {DomQuery}
|
|
11268
11293
|
* @access public
|
|
11269
11294
|
* @category DOMQuery
|
|
@@ -11287,7 +11312,7 @@ DomQuery.$ = {
|
|
|
11287
11312
|
return self;
|
|
11288
11313
|
},
|
|
11289
11314
|
/**
|
|
11290
|
-
* Return the parent node of the first element in this list
|
|
11315
|
+
* Return the parent node of the first element in this list.
|
|
11291
11316
|
*
|
|
11292
11317
|
* @function getParent
|
|
11293
11318
|
* @returns {element}
|
|
@@ -11304,7 +11329,7 @@ DomQuery.$ = {
|
|
|
11304
11329
|
},
|
|
11305
11330
|
/**
|
|
11306
11331
|
* For the first element in this list, insert the first element from the selector before it
|
|
11307
|
-
* in parent element's child nodes list.
|
|
11332
|
+
* in the parent element's child nodes list.
|
|
11308
11333
|
*
|
|
11309
11334
|
* @function insertBefore
|
|
11310
11335
|
* @param {String} selector CSS selector for the element to be inserted before this element
|
|
@@ -11343,7 +11368,7 @@ DomQuery.$ = {
|
|
|
11343
11368
|
return this;
|
|
11344
11369
|
},
|
|
11345
11370
|
/**
|
|
11346
|
-
* Iterate over each element and set the attribute name to the specified value
|
|
11371
|
+
* Iterate over each element and set the attribute name to the specified value.
|
|
11347
11372
|
*
|
|
11348
11373
|
* @function attr
|
|
11349
11374
|
* @param {String} attrName Name of attribute to set
|
|
@@ -11404,10 +11429,10 @@ DomQuery.$ = {
|
|
|
11404
11429
|
return dom(this[index]);
|
|
11405
11430
|
},
|
|
11406
11431
|
/**
|
|
11407
|
-
* Set the height or unset the height for the first element in the list
|
|
11432
|
+
* Set the height or unset the height for the first element in the list.
|
|
11408
11433
|
*
|
|
11409
11434
|
* @function height
|
|
11410
|
-
* @param {Number} height The new height to set. Undefined will remove the height allow it to auto determined.
|
|
11435
|
+
* @param {Number} height The new height to set. Undefined will remove the height and allow it to be auto determined.
|
|
11411
11436
|
* @returns {DomQuery}
|
|
11412
11437
|
* @access public
|
|
11413
11438
|
* @category DOMQuery
|
|
@@ -11428,10 +11453,10 @@ DomQuery.$ = {
|
|
|
11428
11453
|
}
|
|
11429
11454
|
},
|
|
11430
11455
|
/**
|
|
11431
|
-
* Set the width or unset the width for the first element in the list
|
|
11456
|
+
* Set the width or unset the width for the first element in the list.
|
|
11432
11457
|
*
|
|
11433
11458
|
* @function width
|
|
11434
|
-
* @param {Number} width The new width to set. Undefined will remove the width allow it to auto determined.
|
|
11459
|
+
* @param {Number} width The new width to set. Undefined will remove the width and allow it to be auto determined.
|
|
11435
11460
|
* @returns {DomQuery}
|
|
11436
11461
|
* @access public
|
|
11437
11462
|
* @category DOMQuery
|
|
@@ -11452,7 +11477,7 @@ DomQuery.$ = {
|
|
|
11452
11477
|
}
|
|
11453
11478
|
},
|
|
11454
11479
|
/**
|
|
11455
|
-
* For each element in the list, call the element's focus method if it exists
|
|
11480
|
+
* For each element in the list, call the element's focus method if it exists.
|
|
11456
11481
|
*
|
|
11457
11482
|
* @function focus
|
|
11458
11483
|
* @returns {DomQuery}
|
|
@@ -12203,12 +12228,14 @@ function callLater(callback, n) {
|
|
|
12203
12228
|
*
|
|
12204
12229
|
* @access public
|
|
12205
12230
|
* @category Events
|
|
12206
|
-
* @param {
|
|
12231
|
+
* @param {Object} [options] - Options passed through to each queue's flush method
|
|
12232
|
+
* @param {boolean} [options.unload] - signals the page is unloading; drains the send queue using sendBeacon or sync XHR for reliable last-chance delivery
|
|
12233
|
+
* @param {boolean} [options.hidden] - signals the page is being hidden; drains the send queue immediately rather than waiting for the next timer tick
|
|
12207
12234
|
* @returns {void}
|
|
12208
12235
|
* @example
|
|
12209
12236
|
* pendo.flushNow()
|
|
12210
12237
|
*/
|
|
12211
|
-
function flushNow(
|
|
12238
|
+
function flushNow(options) {
|
|
12212
12239
|
try {
|
|
12213
12240
|
_.each(queues, function (queue) {
|
|
12214
12241
|
if (queue.flush) {
|
|
@@ -12221,14 +12248,14 @@ function flushNow(force, options) {
|
|
|
12221
12248
|
}
|
|
12222
12249
|
}
|
|
12223
12250
|
/*
|
|
12224
|
-
* Queue
|
|
12225
|
-
*
|
|
12251
|
+
* Queue {flushNow} for {n} ticks of the event loop, deferring CPU-intensive
|
|
12252
|
+
* compression until the main thread is free.
|
|
12226
12253
|
*/
|
|
12227
12254
|
function flushLater(n) {
|
|
12228
|
-
return callLater(
|
|
12255
|
+
return callLater(flushNow, n);
|
|
12229
12256
|
}
|
|
12230
12257
|
/**
|
|
12231
|
-
* Force a full flush
|
|
12258
|
+
* Force a full flush on {n} ticks
|
|
12232
12259
|
*
|
|
12233
12260
|
* @access private
|
|
12234
12261
|
* @param {number} n ticks to call {flushNow} on
|
|
@@ -12492,7 +12519,7 @@ class LocalStorageEventBuffer {
|
|
|
12492
12519
|
}
|
|
12493
12520
|
read(storage) {
|
|
12494
12521
|
/**
|
|
12495
|
-
* If enabled, Pendo will write pending events to
|
|
12522
|
+
* If enabled, Pendo will write pending events to localStorage before unloading the page
|
|
12496
12523
|
* rather than attempting to send them. The events will be sent the next time the page is loaded.
|
|
12497
12524
|
*
|
|
12498
12525
|
* @name _pendo_unsentEvents
|
|
@@ -13408,6 +13435,7 @@ var makeSafe = function (method, noLogging) {
|
|
|
13408
13435
|
* @function
|
|
13409
13436
|
* @category URL
|
|
13410
13437
|
* @param {string} [url] if not provided, defaults to the current URL from the browser
|
|
13438
|
+
* @returns {boolean | undefined} true if the URL changed and a load event was sent, otherwise undefined
|
|
13411
13439
|
* @example
|
|
13412
13440
|
* pendo.pageLoad()
|
|
13413
13441
|
*/
|
|
@@ -13447,7 +13475,7 @@ pageLoad.reset = function () {
|
|
|
13447
13475
|
|
|
13448
13476
|
/**
|
|
13449
13477
|
* Returns the normalized URL sent from the backend. This won't always
|
|
13450
|
-
* match the desired output from the customer's
|
|
13478
|
+
* match the desired output from the customer's URL customizations if using the location API.
|
|
13451
13479
|
*
|
|
13452
13480
|
* @access public
|
|
13453
13481
|
* @category URL
|
|
@@ -13574,13 +13602,13 @@ function createChannelMatcher(options = {}) {
|
|
|
13574
13602
|
}
|
|
13575
13603
|
/**
|
|
13576
13604
|
* Returns an array of all guides available on the current page to the current user.
|
|
13577
|
-
* If multiple frames on a
|
|
13605
|
+
* If there are multiple frames on a page, `pendo.getActiveGuides()` will return the list of eligible
|
|
13578
13606
|
* guides across all frames. If no frames, this will be the same as `pendo.guides`.
|
|
13579
13607
|
*
|
|
13580
13608
|
* @access public
|
|
13581
13609
|
* @category Guides
|
|
13582
|
-
* @param {object} options - Options for filtering guides
|
|
13583
|
-
* @param {string} options.channel - Channel to filter guides by
|
|
13610
|
+
* @param {object} [options] - Options for filtering guides
|
|
13611
|
+
* @param {string} [options.channel] - Channel to filter guides by
|
|
13584
13612
|
* @returns {Guide[]}
|
|
13585
13613
|
* @example
|
|
13586
13614
|
* pendo.getActiveGuides() => [{ Pendo Guide Object }, ...]
|
|
@@ -13642,7 +13670,7 @@ function findGuideBy(field, value) {
|
|
|
13642
13670
|
*
|
|
13643
13671
|
* @access public
|
|
13644
13672
|
* @category Guides
|
|
13645
|
-
* @param {string}
|
|
13673
|
+
* @param {string} guideId id of the guide as a string
|
|
13646
13674
|
* @returns {Guide | null} JSON guide object or null if no guide found
|
|
13647
13675
|
* @example
|
|
13648
13676
|
* pendo.findGuideById('guide_id')
|
|
@@ -18239,7 +18267,7 @@ var updateVisitorOptions = function (options = {}) {
|
|
|
18239
18267
|
};
|
|
18240
18268
|
};
|
|
18241
18269
|
/**
|
|
18242
|
-
* Updates metadata object for the Pendo Web SDK. Can include visitor and/or account updates, along
|
|
18270
|
+
* Updates the metadata object for the Pendo Web SDK. Can include visitor and/or account updates, along
|
|
18243
18271
|
* with customer-defined metadata values. Changes to identity information will potentially fire
|
|
18244
18272
|
* identity and metadata events, in turn evaluating guide eligibility for the new user and displaying
|
|
18245
18273
|
* any matching guides automatically.
|
|
@@ -18257,11 +18285,11 @@ var updateOptions = makeSafe(function (options) {
|
|
|
18257
18285
|
});
|
|
18258
18286
|
/**
|
|
18259
18287
|
* This function accepts either a string for just the visitor id or it accepts an Object that will contain at least
|
|
18260
|
-
* a visitor object with at least an id field.
|
|
18261
|
-
* visitor object. Also,
|
|
18262
|
-
* also contain other account
|
|
18288
|
+
* a visitor object with at least an id field. It may also contain other visitor-related Key/Value pairs in the
|
|
18289
|
+
* visitor object. Also, the options object may contain an account object that will contain at least an id field. It may
|
|
18290
|
+
* also contain other account-related Key/Value pairs. This will potentially send an identify event and a metadata event.
|
|
18263
18291
|
*
|
|
18264
|
-
* Identifying a visitor will send an event to Pendo and begin loading eligible guides
|
|
18292
|
+
* Identifying a visitor will send an event to Pendo and begin loading eligible guides for the identified user. To remove
|
|
18265
18293
|
* visitor identity use `pendo.clearSession()`.
|
|
18266
18294
|
*
|
|
18267
18295
|
* @access public
|
|
@@ -20677,7 +20705,7 @@ var clearLoopTimer = function () {
|
|
|
20677
20705
|
store.dispatch('guideUpdate/stopScheduledUpdate');
|
|
20678
20706
|
};
|
|
20679
20707
|
/**
|
|
20680
|
-
*
|
|
20708
|
+
* Clears any showing guides and prevents any loaded guides from rendering.
|
|
20681
20709
|
* Loaded guides remain in memory, so calling startGuides will work just fine
|
|
20682
20710
|
* after a stopGuides call.
|
|
20683
20711
|
*
|
|
@@ -20700,7 +20728,7 @@ var stopGuides = function () {
|
|
|
20700
20728
|
};
|
|
20701
20729
|
/**
|
|
20702
20730
|
* Starts the process that loops over all currently loaded guides and
|
|
20703
|
-
* determines what to show. Checks
|
|
20731
|
+
* determines what to show. Checks multi-step guide continuation,
|
|
20704
20732
|
* auto-display guides, launcher guides, and badges.
|
|
20705
20733
|
*
|
|
20706
20734
|
* @access public
|
|
@@ -21968,12 +21996,12 @@ function interceptPreventDefault(EventConstructor, eventList) {
|
|
|
21968
21996
|
*
|
|
21969
21997
|
* @access public
|
|
21970
21998
|
* @category Events
|
|
21971
|
-
* @param {HTMLElement} element DOM element to attach listener
|
|
21999
|
+
* @param {HTMLElement} element DOM element to attach listener to
|
|
21972
22000
|
* @param {string} evt type of DOM event
|
|
21973
22001
|
* @param {Function} fn callback function
|
|
21974
22002
|
* @param {Boolean} useCapture use capture phase instead of bubble
|
|
21975
22003
|
* @example
|
|
21976
|
-
* pendo.attachEvent(pendo.dom("h1")[0], 'click', helloWorld = () => { console.log(Hello World") });
|
|
22004
|
+
* pendo.attachEvent(pendo.dom("h1")[0], 'click', helloWorld = () => { console.log("Hello World") });
|
|
21977
22005
|
*/
|
|
21978
22006
|
function attachEvent(element, evt, fn, useCapture) {
|
|
21979
22007
|
if (!(element && evt && fn)) {
|
|
@@ -21989,12 +22017,12 @@ function attachEvent(element, evt, fn, useCapture) {
|
|
|
21989
22017
|
});
|
|
21990
22018
|
}
|
|
21991
22019
|
/**
|
|
21992
|
-
* Pendo Web SDK's version of detaching event listeners.
|
|
21993
|
-
*
|
|
22020
|
+
* Pendo Web SDK's version of detaching event listeners. The callback must be a named function; anonymous
|
|
22021
|
+
* functions cannot be removed.
|
|
21994
22022
|
*
|
|
21995
22023
|
* @access public
|
|
21996
22024
|
* @category Events
|
|
21997
|
-
* @param {HTMLElement} element DOM element to
|
|
22025
|
+
* @param {HTMLElement} element DOM element to detach listener from
|
|
21998
22026
|
* @param {string} evt type of DOM event
|
|
21999
22027
|
* @param {Function} fn callback function
|
|
22000
22028
|
* @param {Boolean} useCapture use capture phase instead of bubble
|
|
@@ -23303,7 +23331,7 @@ var controlGuideLogMessage = 'Guide was not shown because this visitor is in a c
|
|
|
23303
23331
|
/**
|
|
23304
23332
|
* @constant defaultCssUrl {String}
|
|
23305
23333
|
*
|
|
23306
|
-
* Readonly
|
|
23334
|
+
* Readonly property that provides the default CSS URL based on the customer's Apps configuration with Pendo.
|
|
23307
23335
|
*
|
|
23308
23336
|
* @access public
|
|
23309
23337
|
* @category Guides
|
|
@@ -23398,7 +23426,7 @@ var getStepIdFromElement = function (element) {
|
|
|
23398
23426
|
* In most cases, `pendo.stopGuides()` is preferred since it will stop the loop and guides will not redisplay until `pendo.startGuides()` is called.
|
|
23399
23427
|
*
|
|
23400
23428
|
* Manually hide any active Guides. An argument of an Object containing the property stayHidden set to true needs to be
|
|
23401
|
-
* provided in order for the guides
|
|
23429
|
+
* provided in order for the hidden guides to stay hidden.
|
|
23402
23430
|
*
|
|
23403
23431
|
* @param {Object} - Optional JS Object containing boolean property `stayHidden`
|
|
23404
23432
|
* @access public
|
|
@@ -23481,7 +23509,7 @@ function shouldAffectThrottling(guide, seenReason) {
|
|
|
23481
23509
|
* Hides the current guide and invokes the `guideDismissed` event. Dismissed guides will not
|
|
23482
23510
|
* be re-displayed by default unless they have a recurrence setting or can be reactivated
|
|
23483
23511
|
* with an element. They can always be redisplayed via onGuideAdvanced or onGuidePrevious.
|
|
23484
|
-
|
|
23512
|
+
*
|
|
23485
23513
|
* @access public
|
|
23486
23514
|
* @category Guides
|
|
23487
23515
|
* @example
|
|
@@ -23545,7 +23573,7 @@ var onGuideDismissed = function (evt, step) {
|
|
|
23545
23573
|
};
|
|
23546
23574
|
/**
|
|
23547
23575
|
* Snoozes the current guide. If another guide is eligible to be shown automatically, it will show after snooze.
|
|
23548
|
-
*
|
|
23576
|
+
* The guide will redisplay after one day by default, or a custom `snoozeDuration` can be set in milliseconds as the third argument.
|
|
23549
23577
|
*
|
|
23550
23578
|
* @access public
|
|
23551
23579
|
* @category Guides
|
|
@@ -23660,7 +23688,7 @@ var goToStep = function (evt) {
|
|
|
23660
23688
|
};
|
|
23661
23689
|
/**
|
|
23662
23690
|
* Proceeds to the next step in a multi-step guide and sends a `guideAdvanced` event.
|
|
23663
|
-
* Can
|
|
23691
|
+
* Can advance multiple steps or beyond a specific step by passing optional parameters.
|
|
23664
23692
|
* Lastly, sends a `guideSeen` event for the resulting displayed step.
|
|
23665
23693
|
*
|
|
23666
23694
|
* @access public
|
|
@@ -24222,7 +24250,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24222
24250
|
};
|
|
24223
24251
|
/**
|
|
24224
24252
|
* Returns the normalized URL sent from the backend with the guides payload. This won't always
|
|
24225
|
-
* match the desired output from the customer's
|
|
24253
|
+
* match the desired output from the customer's URL customizations if using the location API.
|
|
24226
24254
|
*
|
|
24227
24255
|
* @access public
|
|
24228
24256
|
* @alias getCurrentUrl
|
|
@@ -24234,6 +24262,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24234
24262
|
* pendo.normalizedUrl
|
|
24235
24263
|
* @example
|
|
24236
24264
|
* pendo.getCurrentUrl()
|
|
24265
|
+
*/
|
|
24237
24266
|
/**
|
|
24238
24267
|
* Activates the Guide for the given name, if loaded. If it is not in the payload,
|
|
24239
24268
|
* this function will return false.
|
|
@@ -24241,7 +24270,7 @@ var getNextStepInMultistep = function (lastSeen, urlToCheck) {
|
|
|
24241
24270
|
* @access public
|
|
24242
24271
|
* @category Guides
|
|
24243
24272
|
* @param {string} name name of the guide to display
|
|
24244
|
-
* @param {string} reason optional reason for the display
|
|
24273
|
+
* @param {string} [reason] optional reason for the display
|
|
24245
24274
|
* @example
|
|
24246
24275
|
* pendo.showGuideByName('guide_name')
|
|
24247
24276
|
*/
|
|
@@ -24263,7 +24292,7 @@ var showGuideByName = function (name, reason) {
|
|
|
24263
24292
|
* @access public
|
|
24264
24293
|
* @category Guides
|
|
24265
24294
|
* @param {string} id id of the guide to display
|
|
24266
|
-
* @param {string} reason optional reason for the display
|
|
24295
|
+
* @param {string} [reason] optional reason for the display
|
|
24267
24296
|
* @example
|
|
24268
24297
|
* pendo.showGuideById('guide_id')
|
|
24269
24298
|
*/
|
|
@@ -24290,7 +24319,7 @@ var resetPendoUI = function () {
|
|
|
24290
24319
|
*
|
|
24291
24320
|
* @access public
|
|
24292
24321
|
* @name doNotProcess
|
|
24293
|
-
* @type {
|
|
24322
|
+
* @type {boolean}
|
|
24294
24323
|
* @category Events
|
|
24295
24324
|
* @example
|
|
24296
24325
|
* pendo.doNotProcess => true
|
|
@@ -24325,15 +24354,13 @@ function guidesPayload(guidesJson) {
|
|
|
24325
24354
|
delete guidesJson.segmentFlags; // This is temporary until the BE stops sending segment flags in the guides payload, at which point this can be removed
|
|
24326
24355
|
}
|
|
24327
24356
|
_.extend(pendo$1, guidesJson);
|
|
24328
|
-
|
|
24329
|
-
|
|
24330
|
-
|
|
24331
|
-
|
|
24332
|
-
|
|
24333
|
-
|
|
24334
|
-
|
|
24335
|
-
}
|
|
24336
|
-
});
|
|
24357
|
+
const guidesReceivedPayload = {
|
|
24358
|
+
guides: pendo$1.guides,
|
|
24359
|
+
visitorId: get_visitor_id(),
|
|
24360
|
+
guideCache
|
|
24361
|
+
};
|
|
24362
|
+
Events.guidesReceived.trigger(guidesReceivedPayload);
|
|
24363
|
+
pendo$1.guides = guidesReceivedPayload.guides;
|
|
24337
24364
|
if (mostRecentGuideRequest.deferred) {
|
|
24338
24365
|
mostRecentGuideRequest.deferred.resolve();
|
|
24339
24366
|
}
|
|
@@ -24515,8 +24542,8 @@ function shouldLoadGuides(visitorId, callback) {
|
|
|
24515
24542
|
return true;
|
|
24516
24543
|
}
|
|
24517
24544
|
/**
|
|
24518
|
-
* Manually load guides for current visitor and URL. This is typically handled automatically by the web SDK
|
|
24519
|
-
* whenever the host Application changes its URL. In rare circumstances, a host Application may
|
|
24545
|
+
* Manually load guides for the current visitor and URL. This is typically handled automatically by the web SDK
|
|
24546
|
+
* whenever the host Application changes its URL. In rare circumstances, a host Application may choose to
|
|
24520
24547
|
* force the load of Guides programmatically. One reason may be in order to get any guides designed for a visitor
|
|
24521
24548
|
* immediately after using a specific part of the Application that doesn't cause a URL change.
|
|
24522
24549
|
*
|
|
@@ -24818,7 +24845,7 @@ function securityPolicyViolationFn(evt) {
|
|
|
24818
24845
|
}
|
|
24819
24846
|
let guideCache;
|
|
24820
24847
|
/**
|
|
24821
|
-
* Resets and starts guide loop
|
|
24848
|
+
* Resets and starts the guide loop.
|
|
24822
24849
|
*
|
|
24823
24850
|
* @access public
|
|
24824
24851
|
* @category Guides
|
|
@@ -24924,7 +24951,7 @@ var initGuides = function (observer) {
|
|
|
24924
24951
|
*/
|
|
24925
24952
|
agentStorage.registry.addLocal(THROTTLING_STATE.SNOOZED);
|
|
24926
24953
|
/**
|
|
24927
|
-
* Used to determine if guides have been blocked
|
|
24954
|
+
* Used to determine if guides have been blocked by the user, an ad blocker, or a failed guide request.
|
|
24928
24955
|
* This will prevent additional guide requests and display attempts, to optimize page performance and
|
|
24929
24956
|
* user experience in cases where guides cannot be loaded.
|
|
24930
24957
|
*
|
|
@@ -24950,7 +24977,7 @@ var initGuides = function (observer) {
|
|
|
24950
24977
|
};
|
|
24951
24978
|
};
|
|
24952
24979
|
/**
|
|
24953
|
-
* Returns true or false
|
|
24980
|
+
* Returns true or false depending on whether the client has disabled guides in the snippet or via a command.
|
|
24954
24981
|
*
|
|
24955
24982
|
* @access public
|
|
24956
24983
|
* @category Guides
|
|
@@ -24962,7 +24989,7 @@ var areGuidesDisabled = function () {
|
|
|
24962
24989
|
return ConfigReader.get('guides.disabled', false) || !pendoCore;
|
|
24963
24990
|
};
|
|
24964
24991
|
/**
|
|
24965
|
-
* Returns true or false
|
|
24992
|
+
* Returns true or false depending on whether the client has delayed guides in the snippet or via a command.
|
|
24966
24993
|
*
|
|
24967
24994
|
* @access public
|
|
24968
24995
|
* @category Guides
|
|
@@ -26418,7 +26445,7 @@ function insertOriginContentHash(originalHash, url, extensionStr, sha256Hash) {
|
|
|
26418
26445
|
}
|
|
26419
26446
|
|
|
26420
26447
|
/**
|
|
26421
|
-
* Formerly `apiKey`.
|
|
26448
|
+
* Formerly `apiKey`. The public app ID associated with the current Pendo installation as a string.
|
|
26422
26449
|
*
|
|
26423
26450
|
* @access public
|
|
26424
26451
|
* @name publicAppId
|
|
@@ -26428,7 +26455,7 @@ function insertOriginContentHash(originalHash, url, extensionStr, sha256Hash) {
|
|
|
26428
26455
|
* pendo.publicAppId => 'PUBLIC_APP_ID'
|
|
26429
26456
|
*/
|
|
26430
26457
|
/**
|
|
26431
|
-
* Formerly `additionalApiKeys`.
|
|
26458
|
+
* Formerly `additionalApiKeys`. An array of additional app IDs that are set in the config. If no primary app ID is set,
|
|
26432
26459
|
* the first in this array will be assigned to `pendo.publicAppId`.
|
|
26433
26460
|
*
|
|
26434
26461
|
* @access public
|
|
@@ -27197,7 +27224,7 @@ var P2AutoLaunch = (function () {
|
|
|
27197
27224
|
function launchDesignerOrPreview(options) {
|
|
27198
27225
|
/**
|
|
27199
27226
|
* Application state while viewing a guide in preview mode. Used while preview mode is active
|
|
27200
|
-
* to track step, status, etc
|
|
27227
|
+
* to track step, status, etc., and cleared when preview mode is exited.
|
|
27201
27228
|
*
|
|
27202
27229
|
* @name pendo-preview
|
|
27203
27230
|
* @category Cookies/localStorage
|
|
@@ -27207,7 +27234,7 @@ function launchDesignerOrPreview(options) {
|
|
|
27207
27234
|
agentStorage.registry.addLocal(pendoPreview$1);
|
|
27208
27235
|
/**
|
|
27209
27236
|
* Application state while previewing a guide from the designer. Used while designer preview is active
|
|
27210
|
-
* to track step, status, etc
|
|
27237
|
+
* to track step, status, etc., and cleared when designer preview is exited.
|
|
27211
27238
|
*
|
|
27212
27239
|
* @name current-guide-preview
|
|
27213
27240
|
* @category Cookies/localStorage
|
|
@@ -28762,7 +28789,7 @@ var ResourceCenterActivity = (function () {
|
|
|
28762
28789
|
})();
|
|
28763
28790
|
|
|
28764
28791
|
/**
|
|
28765
|
-
* Returns boolean representing whether the Pendo Web SDK is fully loaded and has an API key.
|
|
28792
|
+
* Returns a boolean representing whether the Pendo Web SDK is fully loaded and has an API key.
|
|
28766
28793
|
*
|
|
28767
28794
|
* @access public
|
|
28768
28795
|
* @category Core
|
|
@@ -28962,7 +28989,7 @@ function registerEventHandlers({ events = [] }) {
|
|
|
28962
28989
|
function applyDoNotTrackConfigOverrides(options) {
|
|
28963
28990
|
options.excludeNonGuideAnalytics = true;
|
|
28964
28991
|
options.disableCookies = true;
|
|
28965
|
-
options.visitor = { id: '
|
|
28992
|
+
options.visitor = { id: '__cookieless_visitor__' };
|
|
28966
28993
|
delete options.account;
|
|
28967
28994
|
delete options.parentAccount;
|
|
28968
28995
|
}
|
|
@@ -28977,7 +29004,7 @@ const initializeImmediately = 'initializeImmediately';
|
|
|
28977
29004
|
* @function
|
|
28978
29005
|
* @category Core
|
|
28979
29006
|
* @name initialize
|
|
28980
|
-
* @param {object} options identity metadata and configuration to initialize web SDK
|
|
29007
|
+
* @param {object} options identity metadata and configuration to initialize the web SDK
|
|
28981
29008
|
* @see {@link https://support.pendo.io/hc/en-us/articles/360046272771-Developer-s-guide-to-installing-Pendo#what-installation-involves-0-2 | Pendo Installation}
|
|
28982
29009
|
* @example
|
|
28983
29010
|
* pendo.initialize({
|
|
@@ -29080,7 +29107,7 @@ function initialize(options) {
|
|
|
29080
29107
|
teardownFns.push(() => observer.teardown());
|
|
29081
29108
|
if (pendoCore) {
|
|
29082
29109
|
/**
|
|
29083
|
-
* Current visitor id for
|
|
29110
|
+
* Current visitor id for the Pendo installation, either anonymous or identified. Used to determine
|
|
29084
29111
|
* a visitor's guide experience, settings, and associated data.
|
|
29085
29112
|
*
|
|
29086
29113
|
* @name _pendo_visitorId
|
|
@@ -29090,7 +29117,7 @@ function initialize(options) {
|
|
|
29090
29117
|
*/
|
|
29091
29118
|
agentStorage.registry.addLocal(VISITOR_ID_KEY);
|
|
29092
29119
|
/**
|
|
29093
|
-
* Often an anonymous visitor id that is replaced by a logged
|
|
29120
|
+
* Often an anonymous visitor id that is replaced by a logged-in user.
|
|
29094
29121
|
*
|
|
29095
29122
|
* @name _pendo_oldVisitorId
|
|
29096
29123
|
* @category Cookies/localStorage
|
|
@@ -29099,7 +29126,7 @@ function initialize(options) {
|
|
|
29099
29126
|
*/
|
|
29100
29127
|
agentStorage.registry.addLocal(OLD_VISITOR_ID_KEY);
|
|
29101
29128
|
/**
|
|
29102
|
-
* The current account id for
|
|
29129
|
+
* The current account id for the Pendo installation provided in the `pendo.initialize()` call.
|
|
29103
29130
|
*
|
|
29104
29131
|
* @name _pendo_accountId
|
|
29105
29132
|
* @category Cookies/localStorage
|
|
@@ -29135,12 +29162,12 @@ function initialize(options) {
|
|
|
29135
29162
|
teardownFns.push(performanceMonitor.initialize());
|
|
29136
29163
|
}
|
|
29137
29164
|
const flushOnAppHidden = () => {
|
|
29138
|
-
flushNow(
|
|
29165
|
+
flushNow({ hidden: true });
|
|
29139
29166
|
};
|
|
29140
29167
|
Events.appHidden.on(flushOnAppHidden);
|
|
29141
29168
|
teardownFns.push(() => Events.appHidden.off(flushOnAppHidden));
|
|
29142
29169
|
const flushOnAppUnloaded = () => {
|
|
29143
|
-
flushNow(
|
|
29170
|
+
flushNow({ unload: true });
|
|
29144
29171
|
if (localStorageUnloadEnabled) {
|
|
29145
29172
|
localStorageEventBuffer.write(agentStorage);
|
|
29146
29173
|
}
|
|
@@ -29756,13 +29783,20 @@ var BuildingBlockGuides = (function () {
|
|
|
29756
29783
|
detachEvent(targetElement, 'focus', targetElementFocusCallback);
|
|
29757
29784
|
});
|
|
29758
29785
|
}
|
|
29786
|
+
function getTargetElementForStep(step) {
|
|
29787
|
+
if (step.element && step.element !== getBody()) {
|
|
29788
|
+
return step.element;
|
|
29789
|
+
}
|
|
29790
|
+
return null;
|
|
29791
|
+
}
|
|
29759
29792
|
function trapFocusStep(step, guideContainer) {
|
|
29760
|
-
var
|
|
29761
|
-
|
|
29793
|
+
var guideContainerElement = guideContainer.find('#pendo-guide-container');
|
|
29794
|
+
var targetElement = _.get(step, 'attributes.blockOutUI.enabled') && getTargetElementForStep(step);
|
|
29795
|
+
trapFocus(guideContainerElement, targetElement);
|
|
29762
29796
|
}
|
|
29763
29797
|
function getSelectedPollElementForFocus(focusableChildren, bumperElement) {
|
|
29764
29798
|
let elementToFocus;
|
|
29765
|
-
if (bumperElement.getAttribute('type') === 'radio') {
|
|
29799
|
+
if (bumperElement.getAttribute('type') === 'radio' && bumperElement.getAttribute('data-pendo-poll-id')) {
|
|
29766
29800
|
const pollId = bumperElement.getAttribute('data-pendo-poll-id');
|
|
29767
29801
|
elementToFocus = _.find(focusableChildren, function (child) {
|
|
29768
29802
|
const childPollId = child.getAttribute('data-pendo-poll-id');
|
|
@@ -29771,8 +29805,42 @@ var BuildingBlockGuides = (function () {
|
|
|
29771
29805
|
}
|
|
29772
29806
|
return elementToFocus || bumperElement;
|
|
29773
29807
|
}
|
|
29774
|
-
function
|
|
29775
|
-
|
|
29808
|
+
function collectTargetFocusables(targetElement) {
|
|
29809
|
+
if (!targetElement)
|
|
29810
|
+
return [];
|
|
29811
|
+
var focusables = _.toArray(targetElement.querySelectorAll(FOCUSABLE_SELECTORS));
|
|
29812
|
+
if (targetElement.matches(FOCUSABLE_SELECTORS)) {
|
|
29813
|
+
focusables.unshift(targetElement);
|
|
29814
|
+
}
|
|
29815
|
+
return focusables;
|
|
29816
|
+
}
|
|
29817
|
+
function createTargetBumper(className) {
|
|
29818
|
+
var bumper = document.createElement('div');
|
|
29819
|
+
bumper.setAttribute('tabIndex', 0);
|
|
29820
|
+
bumper.setAttribute('class', className);
|
|
29821
|
+
bumper.setAttribute('aria-hidden', 'true');
|
|
29822
|
+
bumper.style.cssText = 'position:absolute !important;width:0 !important;height:0 !important;overflow:hidden !important;outline:none !important;border:none !important;padding:0 !important;margin:0 !important;';
|
|
29823
|
+
return bumper;
|
|
29824
|
+
}
|
|
29825
|
+
function insertTargetBumpers(targetElement) {
|
|
29826
|
+
if (!targetElement || !targetElement.parentNode)
|
|
29827
|
+
return null;
|
|
29828
|
+
var before = createTargetBumper('pendo-before-target-focus-bumper');
|
|
29829
|
+
var after = createTargetBumper('pendo-after-target-focus-bumper');
|
|
29830
|
+
targetElement.parentNode.insertBefore(before, targetElement);
|
|
29831
|
+
targetElement.parentNode.insertBefore(after, targetElement.nextSibling);
|
|
29832
|
+
return { before, after };
|
|
29833
|
+
}
|
|
29834
|
+
function removeTargetBumpers(targetBumpers) {
|
|
29835
|
+
if (!targetBumpers)
|
|
29836
|
+
return;
|
|
29837
|
+
_.each([targetBumpers.before, targetBumpers.after], function (bumper) {
|
|
29838
|
+
if (bumper && bumper.parentNode)
|
|
29839
|
+
bumper.parentNode.removeChild(bumper);
|
|
29840
|
+
});
|
|
29841
|
+
}
|
|
29842
|
+
function trapFocus(guideContainerElement, targetElement) {
|
|
29843
|
+
var containerNode = guideContainerElement[0];
|
|
29776
29844
|
if (!containerNode) {
|
|
29777
29845
|
return;
|
|
29778
29846
|
}
|
|
@@ -29792,43 +29860,75 @@ var BuildingBlockGuides = (function () {
|
|
|
29792
29860
|
// some quirks
|
|
29793
29861
|
'iframe'
|
|
29794
29862
|
].join(', ');
|
|
29795
|
-
var focusableChildren = _.toArray(
|
|
29863
|
+
var focusableChildren = _.toArray(guideContainerElement.find(selectors));
|
|
29796
29864
|
if (!focusableChildren.length) {
|
|
29797
29865
|
return;
|
|
29798
29866
|
}
|
|
29799
29867
|
var firstFocusableEl = focusableChildren[0];
|
|
29800
29868
|
var lastFocusableEl = focusableChildren[focusableChildren.length - 1];
|
|
29801
29869
|
// insert bumpers after the above selectors run for content
|
|
29802
|
-
var bumpers = insertTrapFocusBumpers(
|
|
29870
|
+
var bumpers = insertTrapFocusBumpers(guideContainerElement);
|
|
29803
29871
|
var startFocusBumper = bumpers[0];
|
|
29804
29872
|
var endFocusBumper = bumpers[1];
|
|
29873
|
+
var targetFocusables = collectTargetFocusables(targetElement);
|
|
29874
|
+
var firstTargetFocusable = targetFocusables[0];
|
|
29875
|
+
var lastTargetFocusable = targetFocusables[targetFocusables.length - 1];
|
|
29876
|
+
// Insert bumpers as siblings of the target so we can catch focus crossings even when focus moves through a
|
|
29877
|
+
// cross-origin iframe inside the target (our keydown listener can't see events inside the iframe, but it can
|
|
29878
|
+
// see focus landing on a bumper in the parent document afterwards).
|
|
29879
|
+
var targetBumpers = targetFocusables.length ? insertTargetBumpers(targetElement) : null;
|
|
29880
|
+
var beforeTargetBumper = targetBumpers && targetBumpers.before;
|
|
29881
|
+
var afterTargetBumper = targetBumpers && targetBumpers.after;
|
|
29882
|
+
var targetRoot = targetElement && dom.getRootNode(targetElement);
|
|
29883
|
+
var wrapForward = firstTargetFocusable || firstFocusableEl;
|
|
29884
|
+
var wrapBackward = lastTargetFocusable || lastFocusableEl;
|
|
29805
29885
|
var trapFocusCallback = function (e) {
|
|
29806
|
-
|
|
29807
|
-
var isShiftPressed = e.shiftKey;
|
|
29808
|
-
if (!isTabPressed) {
|
|
29886
|
+
if (!isTabEvent(e)) {
|
|
29809
29887
|
return;
|
|
29810
29888
|
}
|
|
29889
|
+
const isShiftPressed = e.shiftKey;
|
|
29890
|
+
const isKeydown = e.type === 'keydown';
|
|
29811
29891
|
// Check if focus is on the body (clicked on the backdrop), the guide container (starts there when guide opens), or on the focus bumpers
|
|
29812
29892
|
const activeElement = dom.getRootNode(containerNode).activeElement;
|
|
29813
29893
|
const containerActive = activeElement === containerNode;
|
|
29814
29894
|
const bodyActive = document.activeElement === document.body; // if the guide is in a shadow root but you click on the backdrop, the active element is the body of the main document
|
|
29815
|
-
|
|
29895
|
+
const startBumperActive = activeElement === startFocusBumper;
|
|
29896
|
+
const endBumperActive = activeElement === endFocusBumper;
|
|
29897
|
+
const targetActiveElement = targetRoot && targetRoot.activeElement;
|
|
29898
|
+
const beforeTargetBumperActive = !!beforeTargetBumper && targetActiveElement === beforeTargetBumper;
|
|
29899
|
+
const afterTargetBumperActive = !!afterTargetBumper && targetActiveElement === afterTargetBumper;
|
|
29900
|
+
const onLastTargetFocusable = isKeydown && !!lastTargetFocusable && targetActiveElement === lastTargetFocusable;
|
|
29901
|
+
const onFirstTargetFocusable = isKeydown && !!firstTargetFocusable && targetActiveElement === firstTargetFocusable;
|
|
29902
|
+
let elementToFocus;
|
|
29816
29903
|
if (isShiftPressed) {
|
|
29817
|
-
|
|
29818
|
-
|
|
29819
|
-
|
|
29820
|
-
elementToFocus
|
|
29821
|
-
|
|
29822
|
-
|
|
29823
|
-
|
|
29904
|
+
if (onFirstTargetFocusable)
|
|
29905
|
+
elementToFocus = lastFocusableEl;
|
|
29906
|
+
else if (beforeTargetBumperActive)
|
|
29907
|
+
elementToFocus = lastFocusableEl;
|
|
29908
|
+
else if (afterTargetBumperActive)
|
|
29909
|
+
elementToFocus = lastTargetFocusable;
|
|
29910
|
+
else if (startBumperActive || containerActive || bodyActive)
|
|
29911
|
+
elementToFocus = wrapBackward;
|
|
29824
29912
|
}
|
|
29825
29913
|
else {
|
|
29826
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
elementToFocus
|
|
29830
|
-
|
|
29831
|
-
|
|
29914
|
+
if (onLastTargetFocusable)
|
|
29915
|
+
elementToFocus = firstFocusableEl;
|
|
29916
|
+
else if (afterTargetBumperActive)
|
|
29917
|
+
elementToFocus = firstFocusableEl;
|
|
29918
|
+
else if (beforeTargetBumperActive)
|
|
29919
|
+
elementToFocus = firstTargetFocusable;
|
|
29920
|
+
else if (endBumperActive)
|
|
29921
|
+
elementToFocus = wrapForward;
|
|
29922
|
+
else if (containerActive || bodyActive)
|
|
29923
|
+
elementToFocus = firstFocusableEl;
|
|
29924
|
+
}
|
|
29925
|
+
if (elementToFocus) {
|
|
29926
|
+
const resolved = getSelectedPollElementForFocus(focusableChildren, elementToFocus);
|
|
29927
|
+
resolved.focus();
|
|
29928
|
+
if (dom.getRootNode(resolved).activeElement !== resolved) {
|
|
29929
|
+
(isShiftPressed ? lastFocusableEl : firstFocusableEl).focus();
|
|
29930
|
+
}
|
|
29931
|
+
e.preventDefault();
|
|
29832
29932
|
}
|
|
29833
29933
|
};
|
|
29834
29934
|
// attaching to both events helps some edge cases such as breakout by long-pressing the tab
|
|
@@ -29837,6 +29937,7 @@ var BuildingBlockGuides = (function () {
|
|
|
29837
29937
|
Events.one('unmounted', () => {
|
|
29838
29938
|
detachEvent(document, 'keyup', trapFocusCallback);
|
|
29839
29939
|
detachEvent(document, 'keydown', trapFocusCallback);
|
|
29940
|
+
removeTargetBumpers(targetBumpers);
|
|
29840
29941
|
});
|
|
29841
29942
|
}
|
|
29842
29943
|
// bumpers are divs with a tabindex to allow them to be focused, but which should immediately
|
|
@@ -30056,7 +30157,7 @@ var shouldWeLog = function (contexts) {
|
|
|
30056
30157
|
return (!!logOverride || !!isDebuggingEnabled());
|
|
30057
30158
|
};
|
|
30058
30159
|
/**
|
|
30059
|
-
* Logs
|
|
30160
|
+
* Logs output to the console as the [Pendo Web SDK].
|
|
30060
30161
|
*
|
|
30061
30162
|
* @access public
|
|
30062
30163
|
* @category Debugging
|
|
@@ -30174,12 +30275,12 @@ function collectEventHelper({ type, name, props, eventProperties }) {
|
|
|
30174
30275
|
collectEvent(type, correctedProps, url, name, correctedEventProperties);
|
|
30175
30276
|
}
|
|
30176
30277
|
/**
|
|
30177
|
-
* Method to manually track events. Requires a non-empty name string to collect event.
|
|
30278
|
+
* Method to manually track events. Requires a non-empty name string to collect the event.
|
|
30178
30279
|
*
|
|
30179
30280
|
* @access public
|
|
30180
30281
|
* @category Events
|
|
30181
30282
|
* @param {string} name name of the collected event
|
|
30182
|
-
* @param {Object} [props] optional properties object to collect with
|
|
30283
|
+
* @param {Object} [props] optional properties object to collect with the event
|
|
30183
30284
|
* @param {Object} [eventProperties] optional key-value map stored on the event as top-level event properties
|
|
30184
30285
|
* @example
|
|
30185
30286
|
* pendo.track('scroll')
|
|
@@ -30196,7 +30297,7 @@ const privacyFilterCache = new Map();
|
|
|
30196
30297
|
*
|
|
30197
30298
|
* @access public
|
|
30198
30299
|
* @category Events
|
|
30199
|
-
* @param {string} type type of the collected agentic event
|
|
30300
|
+
* @param {string} type type of the collected agentic event (e.g. 'prompt', 'agent_response', 'user_reaction')
|
|
30200
30301
|
* @param {Object} props event-specific properties object
|
|
30201
30302
|
* @param {Object} [eventProperties] optional key-value map stored on the event as top-level event properties (same as pendo.track)
|
|
30202
30303
|
* @example
|
|
@@ -30272,7 +30373,7 @@ function getCachedRegex(filterPattern) {
|
|
|
30272
30373
|
}
|
|
30273
30374
|
|
|
30274
30375
|
/**
|
|
30275
|
-
* Checks visitor and account metadata in the current Pendo installation. Either logs to console
|
|
30376
|
+
* Checks visitor and account metadata in the current Pendo installation. Either logs to the console
|
|
30276
30377
|
* or returns an array with the results of validation.
|
|
30277
30378
|
*
|
|
30278
30379
|
* @access public
|
|
@@ -30534,7 +30635,7 @@ var validateBuiltInGlobals = function (skipLogging) {
|
|
|
30534
30635
|
}
|
|
30535
30636
|
};
|
|
30536
30637
|
/**
|
|
30537
|
-
* Checks current URL of the browser for customized or sanitized
|
|
30638
|
+
* Checks the current URL of the browser for strings customized or sanitized by the application.
|
|
30538
30639
|
*
|
|
30539
30640
|
* @access public
|
|
30540
30641
|
* @category Validation
|
|
@@ -30623,6 +30724,7 @@ const validatePluginsAndExtensions = (skipLogging) => {
|
|
|
30623
30724
|
*
|
|
30624
30725
|
* @access public
|
|
30625
30726
|
* @category Validation
|
|
30727
|
+
* @param {boolean} [skipLogging] does not log output to console if true, returning the environment object instead
|
|
30626
30728
|
* @example
|
|
30627
30729
|
* pendo.validateEnvironment()
|
|
30628
30730
|
*/
|
|
@@ -31111,7 +31213,7 @@ const DEFAULT_GUIDE_SEEN_TIMEOUT_LENGTH = 10000;
|
|
|
31111
31213
|
* @constant guideSeenTimeoutLength {number}
|
|
31112
31214
|
*
|
|
31113
31215
|
* Readonly number that indicates how long a guide will try to show before sending an error.
|
|
31114
|
-
* Defaults to 10 seconds.
|
|
31216
|
+
* Defaults to 10 seconds (10000 ms).
|
|
31115
31217
|
*
|
|
31116
31218
|
* @access public
|
|
31117
31219
|
* @category Guides
|
|
@@ -31229,9 +31331,7 @@ function exportPublicApi(pendo) {
|
|
|
31229
31331
|
pendo.VERSION = VERSION;
|
|
31230
31332
|
pendo.LOADER = LOADER;
|
|
31231
31333
|
// cache.js
|
|
31232
|
-
pendo.flushNow = exportPendoCoreOnly(
|
|
31233
|
-
return flushNow(true, options);
|
|
31234
|
-
});
|
|
31334
|
+
pendo.flushNow = exportPendoCoreOnly(flushNow);
|
|
31235
31335
|
pendo.teardown = makeSafe(teardown);
|
|
31236
31336
|
// guides.js
|
|
31237
31337
|
pendo.initGuides = exportPendoCoreOnly(initGuides);
|
|
@@ -31374,7 +31474,7 @@ function exportPublicApi(pendo) {
|
|
|
31374
31474
|
pendo.receiveDomStructureJson = exportPendoCoreOnly(ContentLoader.receiveDomStructureJson);
|
|
31375
31475
|
pendo.addExtension = addExtension;
|
|
31376
31476
|
/**
|
|
31377
|
-
* Retrieve a configuration value from the web
|
|
31477
|
+
* Retrieve a configuration value from the web SDK's config. Available configuration keys can be
|
|
31378
31478
|
* found in the [configuration section](/config).
|
|
31379
31479
|
*
|
|
31380
31480
|
* @access public
|
|
@@ -31624,7 +31724,7 @@ function Guide() {
|
|
|
31624
31724
|
return true;
|
|
31625
31725
|
};
|
|
31626
31726
|
/**
|
|
31627
|
-
* Returns a Boolean value to indicate if the Guide can
|
|
31727
|
+
* Returns a Boolean value to indicate if the Guide can show at this time.
|
|
31628
31728
|
*
|
|
31629
31729
|
* @access public
|
|
31630
31730
|
* @category Guides
|
|
@@ -31657,13 +31757,13 @@ function Guide() {
|
|
|
31657
31757
|
return promise;
|
|
31658
31758
|
};
|
|
31659
31759
|
/**
|
|
31660
|
-
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
|
|
31666
|
-
|
|
31760
|
+
* Attempt to show the Guide. The Guide will still honor any constraints like
|
|
31761
|
+
* requiring a DOM element to be present if it was configured for that.
|
|
31762
|
+
*
|
|
31763
|
+
* @access public
|
|
31764
|
+
* @category Guides
|
|
31765
|
+
* @returns {void}
|
|
31766
|
+
*/
|
|
31667
31767
|
this.show = function (reason) {
|
|
31668
31768
|
var guide = this;
|
|
31669
31769
|
return joinShowPromises(_.map(guide.steps, function (step) {
|
|
@@ -31677,7 +31777,7 @@ function Guide() {
|
|
|
31677
31777
|
*
|
|
31678
31778
|
* @access public
|
|
31679
31779
|
* @category Guides
|
|
31680
|
-
* @returns {
|
|
31780
|
+
* @returns {void}
|
|
31681
31781
|
* @example
|
|
31682
31782
|
* guide.hide({stayHidden: true});
|
|
31683
31783
|
*/
|
|
@@ -32774,7 +32874,7 @@ function GuideStep(guide) {
|
|
|
32774
32874
|
removeStyleElementsForIdFromHead(this.id);
|
|
32775
32875
|
};
|
|
32776
32876
|
/**
|
|
32777
|
-
*
|
|
32877
|
+
* Attempts to show the step.
|
|
32778
32878
|
*
|
|
32779
32879
|
* @access public
|
|
32780
32880
|
* @category Guides
|
|
@@ -32955,7 +33055,7 @@ function GuideStep(guide) {
|
|
|
32955
33055
|
/**
|
|
32956
33056
|
* Hides the Step if shown. Use an argument of an Object containing a
|
|
32957
33057
|
* key of `stayHidden` set to `true` to make sure to keep the Step hidden
|
|
32958
|
-
* if the Guide it belongs to is designated as
|
|
33058
|
+
* if the Guide it belongs to is designated as automatically shown.
|
|
32959
33059
|
*
|
|
32960
33060
|
* @access public
|
|
32961
33061
|
* @category Guides
|
|
@@ -33006,7 +33106,7 @@ function GuideStep(guide) {
|
|
|
33006
33106
|
*
|
|
33007
33107
|
* @access public
|
|
33008
33108
|
* @category Guides
|
|
33009
|
-
* @returns {
|
|
33109
|
+
* @returns {void}
|
|
33010
33110
|
*/
|
|
33011
33111
|
this.dismiss = function () {
|
|
33012
33112
|
if (this.seenState === 'dismissed' && !this.isRendered())
|
|
@@ -33032,9 +33132,9 @@ function GuideStep(guide) {
|
|
|
33032
33132
|
* Allows for an eventListener to be created that will automatically get cleaned up when this
|
|
33033
33133
|
* Step is torn down.
|
|
33034
33134
|
*
|
|
33035
|
-
* @param element {Element} - The DOM element to attach the listener.
|
|
33135
|
+
* @param element {Element} - The DOM element to attach the listener to.
|
|
33036
33136
|
* @param type {String} - The type of event: 'click', 'mousedown', 'keypress', etc...
|
|
33037
|
-
* @param fn {function} - A function that will be called when an event
|
|
33137
|
+
* @param fn {function} - A function that will be called when an event of the specified type occurs.
|
|
33038
33138
|
*
|
|
33039
33139
|
* @access public
|
|
33040
33140
|
* @category Guides
|
|
@@ -33192,7 +33292,7 @@ class CloneDetection {
|
|
|
33192
33292
|
return;
|
|
33193
33293
|
/**
|
|
33194
33294
|
* Randomly generated ID used to detect when sessionStorage has been cloned
|
|
33195
|
-
* from another browser
|
|
33295
|
+
* from another browser tab.
|
|
33196
33296
|
*
|
|
33197
33297
|
* @name pendo_cd
|
|
33198
33298
|
* @category Cookies/sessionStorage
|
|
@@ -33309,7 +33409,7 @@ var FramesModule = (function () {
|
|
|
33309
33409
|
if (state.initialized)
|
|
33310
33410
|
return;
|
|
33311
33411
|
/**
|
|
33312
|
-
* Randomly generated string that identifies a browser
|
|
33412
|
+
* Randomly generated string that identifies a browser tab.
|
|
33313
33413
|
*
|
|
33314
33414
|
* @name pendo_tabId
|
|
33315
33415
|
* @category Cookies/sessionStorage
|
|
@@ -33318,7 +33418,7 @@ var FramesModule = (function () {
|
|
|
33318
33418
|
*/
|
|
33319
33419
|
agentStorage.registry.addSession(TAB_ID);
|
|
33320
33420
|
/**
|
|
33321
|
-
* When a browser
|
|
33421
|
+
* When a browser tab is cloned, the `pendo_tabId` is copied to the new tab.
|
|
33322
33422
|
* The Pendo Web SDK detects this, creates a new `pendo_tabId`, and stores the old
|
|
33323
33423
|
* `pendo_tabId` in `pendo_parentTabId`.
|
|
33324
33424
|
*
|
|
@@ -35397,7 +35497,7 @@ function addDebuggingFunctions() {
|
|
|
35397
35497
|
pendo$1.debugging = debugging;
|
|
35398
35498
|
}
|
|
35399
35499
|
/**
|
|
35400
|
-
* Loads Pendo Debugger and extends the global pendo object with additional functionality
|
|
35500
|
+
* Loads the Pendo Debugger and extends the global `pendo` object with additional functionality
|
|
35401
35501
|
* for debugging purposes.
|
|
35402
35502
|
*
|
|
35403
35503
|
* @access public
|
|
@@ -35424,7 +35524,7 @@ function enableDebugging(andChain) {
|
|
|
35424
35524
|
return 'debugging enabled';
|
|
35425
35525
|
}
|
|
35426
35526
|
/**
|
|
35427
|
-
* Removes Pendo Debugger extension.
|
|
35527
|
+
* Removes the Pendo Debugger extension.
|
|
35428
35528
|
*
|
|
35429
35529
|
* @access public
|
|
35430
35530
|
* @category Debugging
|
|
@@ -35503,7 +35603,7 @@ const DebuggerLauncher = (function () {
|
|
|
35503
35603
|
}
|
|
35504
35604
|
globalPendo = pendo;
|
|
35505
35605
|
/**
|
|
35506
|
-
* Returns a string indicating debugging status. Pass an optional value of true to get result as a boolean.
|
|
35606
|
+
* Returns a string indicating debugging status. Pass an optional value of true to get the result as a boolean.
|
|
35507
35607
|
*
|
|
35508
35608
|
* @access public
|
|
35509
35609
|
* @category Debugging
|
|
@@ -36081,7 +36181,7 @@ const EmbeddedGuides = (function () {
|
|
|
36081
36181
|
}
|
|
36082
36182
|
})();
|
|
36083
36183
|
/**
|
|
36084
|
-
* Returns a list of embedded guides eligible
|
|
36184
|
+
* Returns a list of embedded guides eligible for the active visitor on the active page.
|
|
36085
36185
|
*
|
|
36086
36186
|
* @access public
|
|
36087
36187
|
* @category Guides
|
|
@@ -36093,7 +36193,7 @@ function getEmbeddedGuides() {
|
|
|
36093
36193
|
return EmbeddedGuides.activeEmbeddedGuides;
|
|
36094
36194
|
}
|
|
36095
36195
|
/**
|
|
36096
|
-
* Returns a list of embedded guides that are rendered on the page
|
|
36196
|
+
* Returns a list of embedded guides that are rendered on the page.
|
|
36097
36197
|
*
|
|
36098
36198
|
* @access public
|
|
36099
36199
|
* @category Guides
|
|
@@ -37357,6 +37457,126 @@ const FrustrationEvent = (function () {
|
|
|
37357
37457
|
}
|
|
37358
37458
|
})();
|
|
37359
37459
|
|
|
37460
|
+
const snapshots = {};
|
|
37461
|
+
function snapshotKey(guideId, stepId) {
|
|
37462
|
+
return `${guideId}:${stepId}`;
|
|
37463
|
+
}
|
|
37464
|
+
function isPlaceholderGuide(guide) {
|
|
37465
|
+
return _.keys(guide).length === 1 && guide.id;
|
|
37466
|
+
}
|
|
37467
|
+
function recordGuideResponseSnapshots(guidesFromResponse, guideCache) {
|
|
37468
|
+
if (!guidesFromResponse || !guideCache) {
|
|
37469
|
+
return;
|
|
37470
|
+
}
|
|
37471
|
+
_.each(guidesFromResponse, function (guide) {
|
|
37472
|
+
if (!guide || !guide.id) {
|
|
37473
|
+
return;
|
|
37474
|
+
}
|
|
37475
|
+
if (isPlaceholderGuide(guide)) {
|
|
37476
|
+
const priorCached = guideCache.get(guide.id);
|
|
37477
|
+
if (!priorCached || !priorCached.steps) {
|
|
37478
|
+
return;
|
|
37479
|
+
}
|
|
37480
|
+
_.each(priorCached.steps, function (step) {
|
|
37481
|
+
if (!step || !step.id) {
|
|
37482
|
+
return;
|
|
37483
|
+
}
|
|
37484
|
+
const entry = { payload_seen_state: null };
|
|
37485
|
+
if (!_.isUndefined(step.seenState) && step.seenState !== null) {
|
|
37486
|
+
entry.cached_seen_state = step.seenState;
|
|
37487
|
+
}
|
|
37488
|
+
snapshots[snapshotKey(guide.id, step.id)] = entry;
|
|
37489
|
+
});
|
|
37490
|
+
return;
|
|
37491
|
+
}
|
|
37492
|
+
const priorCached = guideCache.get(guide.id);
|
|
37493
|
+
_.each(guide.steps || [], function (step) {
|
|
37494
|
+
if (!step || !step.id) {
|
|
37495
|
+
return;
|
|
37496
|
+
}
|
|
37497
|
+
const entry = {
|
|
37498
|
+
payload_seen_state: _.isUndefined(step.seenState) ? null : step.seenState
|
|
37499
|
+
};
|
|
37500
|
+
const cachedStep = priorCached && _.findWhere(priorCached.steps, { id: step.id });
|
|
37501
|
+
if (cachedStep && !_.isUndefined(cachedStep.seenState) && cachedStep.seenState !== null) {
|
|
37502
|
+
entry.cached_seen_state = cachedStep.seenState;
|
|
37503
|
+
}
|
|
37504
|
+
snapshots[snapshotKey(guide.id, step.id)] = entry;
|
|
37505
|
+
});
|
|
37506
|
+
});
|
|
37507
|
+
}
|
|
37508
|
+
function mergeGuidesWithCache(guidesFromResponse, visitorId, guideCache) {
|
|
37509
|
+
if (!guidesFromResponse) {
|
|
37510
|
+
return guidesFromResponse;
|
|
37511
|
+
}
|
|
37512
|
+
if (!guideCache) {
|
|
37513
|
+
return guidesFromResponse;
|
|
37514
|
+
}
|
|
37515
|
+
return _.map(guidesFromResponse, function (guide) {
|
|
37516
|
+
if (isPlaceholderGuide(guide)) {
|
|
37517
|
+
return guideCache.get(guide.id);
|
|
37518
|
+
}
|
|
37519
|
+
guideCache.add(guide, visitorId);
|
|
37520
|
+
return guide;
|
|
37521
|
+
});
|
|
37522
|
+
}
|
|
37523
|
+
function getSnapshot(guideId, stepId) {
|
|
37524
|
+
return snapshots[snapshotKey(guideId, stepId)];
|
|
37525
|
+
}
|
|
37526
|
+
function clearSnapshots() {
|
|
37527
|
+
_.each(_.keys(snapshots), function (key) {
|
|
37528
|
+
delete snapshots[key];
|
|
37529
|
+
});
|
|
37530
|
+
}
|
|
37531
|
+
|
|
37532
|
+
const GuideCachePlugin = {
|
|
37533
|
+
name: 'GuideCache',
|
|
37534
|
+
initialize(pendo, PluginAPI) {
|
|
37535
|
+
this.onGuidesReceived = _.bind(this.guidesReceived, this);
|
|
37536
|
+
this.onEventCaptured = _.bind(this.eventCaptured, this);
|
|
37537
|
+
PluginAPI.Events.on('guidesReceived', this.onGuidesReceived);
|
|
37538
|
+
this.subscriptions = [
|
|
37539
|
+
PluginAPI.attachEvent(PluginAPI.Events, 'eventCaptured', this.onEventCaptured)
|
|
37540
|
+
];
|
|
37541
|
+
},
|
|
37542
|
+
teardown(pendo, PluginAPI) {
|
|
37543
|
+
PluginAPI.Events.off('guidesReceived', this.onGuidesReceived);
|
|
37544
|
+
_.each(this.subscriptions, function (unsubscribe) {
|
|
37545
|
+
unsubscribe();
|
|
37546
|
+
});
|
|
37547
|
+
this.subscriptions = [];
|
|
37548
|
+
},
|
|
37549
|
+
guidesReceived(event) {
|
|
37550
|
+
clearSnapshots();
|
|
37551
|
+
const payload = event.data[0];
|
|
37552
|
+
if (!payload || !payload.guideCache || !payload.guides) {
|
|
37553
|
+
return;
|
|
37554
|
+
}
|
|
37555
|
+
recordGuideResponseSnapshots(payload.guides, payload.guideCache);
|
|
37556
|
+
payload.guides = mergeGuidesWithCache(payload.guides, payload.visitorId, payload.guideCache);
|
|
37557
|
+
},
|
|
37558
|
+
eventCaptured(event) {
|
|
37559
|
+
if (!event || !event.data || !event.data.length) {
|
|
37560
|
+
return;
|
|
37561
|
+
}
|
|
37562
|
+
const capturedEvent = event.data[0];
|
|
37563
|
+
if (!capturedEvent || capturedEvent.type !== 'guideSeen') {
|
|
37564
|
+
return;
|
|
37565
|
+
}
|
|
37566
|
+
if (capturedEvent.props.reason !== 'auto') {
|
|
37567
|
+
return;
|
|
37568
|
+
}
|
|
37569
|
+
const snap = getSnapshot(capturedEvent.props.guide_id, capturedEvent.props.guide_step_id);
|
|
37570
|
+
if (!snap) {
|
|
37571
|
+
return;
|
|
37572
|
+
}
|
|
37573
|
+
capturedEvent.props.payload_seen_state = snap.payload_seen_state;
|
|
37574
|
+
if (!_.isUndefined(snap.cached_seen_state)) {
|
|
37575
|
+
capturedEvent.props.cached_seen_state = snap.cached_seen_state;
|
|
37576
|
+
}
|
|
37577
|
+
}
|
|
37578
|
+
};
|
|
37579
|
+
|
|
37360
37580
|
const IFrameMonitor = (function () {
|
|
37361
37581
|
const FRAME_TIMER_LENGTH = 250;
|
|
37362
37582
|
const FRAME_ID = 'pendo-loader';
|
|
@@ -39031,7 +39251,7 @@ var doesLauncherHaveGuides = function () {
|
|
|
39031
39251
|
return dom('._pendo-launcher-item_').length > 0;
|
|
39032
39252
|
};
|
|
39033
39253
|
/**
|
|
39034
|
-
* Closes Pendo Guide Center (launcher) if open on page.
|
|
39254
|
+
* Closes the Pendo Guide Center (launcher) if open on the page.
|
|
39035
39255
|
*
|
|
39036
39256
|
* @access public
|
|
39037
39257
|
* @category Classic Guides
|
|
@@ -39049,7 +39269,7 @@ var collapseLauncherList = function () {
|
|
|
39049
39269
|
}
|
|
39050
39270
|
};
|
|
39051
39271
|
/**
|
|
39052
|
-
* Opens Pendo Guide Center (launcher) if present on page.
|
|
39272
|
+
* Opens the Pendo Guide Center (launcher) if present on the page.
|
|
39053
39273
|
*
|
|
39054
39274
|
* @access public
|
|
39055
39275
|
* @category Classic Guides
|
|
@@ -39162,7 +39382,7 @@ var initLauncherPlugin = function (pendo, PluginAPI) {
|
|
|
39162
39382
|
PluginAPI.GuideLoop.addUpdatePhase(launcherProc);
|
|
39163
39383
|
registerLoadGuideJobs(loadLauncherContentHandler);
|
|
39164
39384
|
/**
|
|
39165
|
-
* Written when the classic guide center is closed. Legacy guide center only
|
|
39385
|
+
* Written when the classic guide center is closed. Legacy guide center only; not used for the resource center.
|
|
39166
39386
|
*
|
|
39167
39387
|
* @name _pendo_launcher-closed
|
|
39168
39388
|
* @category Cookies/localStorage
|
|
@@ -39367,7 +39587,7 @@ var PromoteMetadata = (function () {
|
|
|
39367
39587
|
promotedAgentMetadata = PluginAPI.ConfigReader.get(PROMOTED_AGENT_METADATA);
|
|
39368
39588
|
schemaGroup = {};
|
|
39369
39589
|
/**
|
|
39370
|
-
* Stores the historical metadata fields for the current visitor
|
|
39590
|
+
* Stores the historical metadata fields for the current visitor when enabled in an application.
|
|
39371
39591
|
* This is turned on by an admin in Pendo's Data Mappings and used to track metadata changes over time.
|
|
39372
39592
|
*
|
|
39373
39593
|
* @name _pendo___sg__
|
|
@@ -39972,6 +40192,364 @@ class DOMPrompt {
|
|
|
39972
40192
|
}
|
|
39973
40193
|
}
|
|
39974
40194
|
|
|
40195
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
40196
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
40197
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
40198
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
40199
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
40200
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
40201
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
40202
|
+
const THUMB_DOWN = 'thumbDown';
|
|
40203
|
+
const THUMB_UP = 'thumbUp';
|
|
40204
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
40205
|
+
const TURN_ATTR = 'turnAttr';
|
|
40206
|
+
const USER_MESSAGE = 'userMessage';
|
|
40207
|
+
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
40208
|
+
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
40209
|
+
const REQUIRED_SELECTORS = [
|
|
40210
|
+
ASSISTANT_MESSAGE,
|
|
40211
|
+
CONVERSATION_ID_URL_PATTERN,
|
|
40212
|
+
MESSAGE_ID_ATTR,
|
|
40213
|
+
STREAMING_ACTIVE,
|
|
40214
|
+
TURN_CONTAINER,
|
|
40215
|
+
TURN_ATTR,
|
|
40216
|
+
USER_MESSAGE
|
|
40217
|
+
];
|
|
40218
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
40219
|
+
const SUBMISSION_START_RETRY_MS = 1000;
|
|
40220
|
+
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
40221
|
+
class DOMConversation {
|
|
40222
|
+
// Returns the list of required selector types that are missing or empty
|
|
40223
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
40224
|
+
// valid for instantiation.
|
|
40225
|
+
static validateConfig(cssSelectors) {
|
|
40226
|
+
if (!Array.isArray(cssSelectors)) {
|
|
40227
|
+
return REQUIRED_SELECTORS.slice();
|
|
40228
|
+
}
|
|
40229
|
+
const present = new Set();
|
|
40230
|
+
for (const cfg of cssSelectors) {
|
|
40231
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
40232
|
+
continue;
|
|
40233
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
40234
|
+
try {
|
|
40235
|
+
RegExp(cfg.cssSelector);
|
|
40236
|
+
}
|
|
40237
|
+
catch (e) {
|
|
40238
|
+
continue;
|
|
40239
|
+
}
|
|
40240
|
+
}
|
|
40241
|
+
present.add(cfg.type);
|
|
40242
|
+
}
|
|
40243
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
40244
|
+
}
|
|
40245
|
+
static supportedPreset(preset) {
|
|
40246
|
+
return preset === 'chatgpt-full';
|
|
40247
|
+
}
|
|
40248
|
+
constructor(pendo, PluginAPI, id, privacyFilters, cssSelectors) {
|
|
40249
|
+
this.selectors = {};
|
|
40250
|
+
this.listeners = [];
|
|
40251
|
+
this.isActive = true;
|
|
40252
|
+
this.observers = [];
|
|
40253
|
+
this.wasStreaming = false;
|
|
40254
|
+
this.streamingEndTimer = null;
|
|
40255
|
+
this.submissionStartRetryTimer = null;
|
|
40256
|
+
this.requestNode = null;
|
|
40257
|
+
this.conversationIdRegex = null;
|
|
40258
|
+
this.customAgentIdRegex = null;
|
|
40259
|
+
this.lastReturnedMessageId = null;
|
|
40260
|
+
this.dom = pendo.dom;
|
|
40261
|
+
this._ = pendo._;
|
|
40262
|
+
this.api = PluginAPI;
|
|
40263
|
+
this.Sizzle = pendo.Sizzle;
|
|
40264
|
+
this.id = id;
|
|
40265
|
+
this.setFilters(privacyFilters);
|
|
40266
|
+
if (!this._.isArray(cssSelectors)) {
|
|
40267
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
40268
|
+
cssSelectors = [];
|
|
40269
|
+
}
|
|
40270
|
+
this._.each(cssSelectors, (cfg) => {
|
|
40271
|
+
if (cfg && cfg.type) {
|
|
40272
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
40273
|
+
}
|
|
40274
|
+
});
|
|
40275
|
+
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
40276
|
+
const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
|
|
40277
|
+
if (customAgentIdUrlPattern) { // this is optional
|
|
40278
|
+
try {
|
|
40279
|
+
this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
|
|
40280
|
+
}
|
|
40281
|
+
catch (error) {
|
|
40282
|
+
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
40283
|
+
}
|
|
40284
|
+
}
|
|
40285
|
+
this.root = document.body;
|
|
40286
|
+
this.setupReactionListener();
|
|
40287
|
+
this.setupStreamingObserver();
|
|
40288
|
+
}
|
|
40289
|
+
setupReactionListener() {
|
|
40290
|
+
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
40291
|
+
return;
|
|
40292
|
+
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
40293
|
+
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
40294
|
+
}
|
|
40295
|
+
handleReactionClick(evt) {
|
|
40296
|
+
const target = evt.target;
|
|
40297
|
+
if (!target || target.nodeType !== 1)
|
|
40298
|
+
return;
|
|
40299
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
40300
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
40301
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
40302
|
+
if (!thumb.length)
|
|
40303
|
+
return;
|
|
40304
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
40305
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
40306
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
40307
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
40308
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
40309
|
+
const assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
40310
|
+
.find(this.findSelector(ASSISTANT_MESSAGE));
|
|
40311
|
+
this.emit('user_reaction', {
|
|
40312
|
+
agentId: this.id,
|
|
40313
|
+
messageId: this.getMessageId(assistantNode),
|
|
40314
|
+
content,
|
|
40315
|
+
privacyFilterApplied: false
|
|
40316
|
+
});
|
|
40317
|
+
}
|
|
40318
|
+
// observe the streaming indicator
|
|
40319
|
+
setupStreamingObserver() {
|
|
40320
|
+
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
40321
|
+
this.stopStreamingEndTimer();
|
|
40322
|
+
const MutationObserver = getZoneSafeMethod('MutationObserver');
|
|
40323
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
40324
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
40325
|
+
observer.observe(this.root, {
|
|
40326
|
+
childList: true,
|
|
40327
|
+
subtree: true,
|
|
40328
|
+
attributes: true,
|
|
40329
|
+
attributeFilter: attrName ? [attrName] : undefined
|
|
40330
|
+
});
|
|
40331
|
+
this.observers.push(observer);
|
|
40332
|
+
}
|
|
40333
|
+
// look for changes in the state of the streaming indicator.
|
|
40334
|
+
// streaming started -> a prompt has been submitted
|
|
40335
|
+
// streaming ended -> got a response
|
|
40336
|
+
// we don't send the prompt immediately when it's submitted because it might not have a
|
|
40337
|
+
// conversation id yet.
|
|
40338
|
+
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
40339
|
+
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
40340
|
+
// end-handling is deferred by a short settle window
|
|
40341
|
+
handleMutation() {
|
|
40342
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
40343
|
+
if (isStreaming === this.wasStreaming)
|
|
40344
|
+
return;
|
|
40345
|
+
if (isStreaming) { // started streaming
|
|
40346
|
+
if (!this.streamingEndTimer) {
|
|
40347
|
+
this.onSubmissionStart();
|
|
40348
|
+
}
|
|
40349
|
+
else {
|
|
40350
|
+
// stream restarted during the settle window (multi-phase response).
|
|
40351
|
+
// treat as a continuation of the prior request, not a new submission.
|
|
40352
|
+
// we'll handle it next time streaming stops
|
|
40353
|
+
this.stopStreamingEndTimer();
|
|
40354
|
+
}
|
|
40355
|
+
}
|
|
40356
|
+
else { // finished streaming
|
|
40357
|
+
this.startStreamingEndTimer();
|
|
40358
|
+
}
|
|
40359
|
+
this.wasStreaming = isStreaming;
|
|
40360
|
+
}
|
|
40361
|
+
onSubmissionStart(attempt = 1) {
|
|
40362
|
+
this.requestNode = this.findLastRequestNode();
|
|
40363
|
+
if (this.requestNode) {
|
|
40364
|
+
this.handleUserMessage(this.requestNode);
|
|
40365
|
+
return;
|
|
40366
|
+
}
|
|
40367
|
+
// URL hasn't flipped yet to include the conversation id on a fresh chat
|
|
40368
|
+
// retry, if that still fails, onSubmissionEnd handles it
|
|
40369
|
+
if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
|
|
40370
|
+
this.startSubmissionStartRetryTimer(attempt + 1);
|
|
40371
|
+
}
|
|
40372
|
+
}
|
|
40373
|
+
onSubmissionEnd() {
|
|
40374
|
+
this.stopSubmissionStartRetryTimer();
|
|
40375
|
+
let requestNode = this.requestNode;
|
|
40376
|
+
this.requestNode = null;
|
|
40377
|
+
if (!requestNode) {
|
|
40378
|
+
// onSubmissionStart didn't send, send it now
|
|
40379
|
+
requestNode = this.findLastRequestNode();
|
|
40380
|
+
if (!requestNode)
|
|
40381
|
+
return;
|
|
40382
|
+
this.handleUserMessage(requestNode);
|
|
40383
|
+
}
|
|
40384
|
+
const requestTurn = this.findTurnNumber(requestNode);
|
|
40385
|
+
if (requestTurn === null)
|
|
40386
|
+
return;
|
|
40387
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
40388
|
+
const toEmit = [];
|
|
40389
|
+
for (let i = assistantNodes.length - 1; i >= 0; i--) {
|
|
40390
|
+
const n = this.findTurnNumber(this.dom(assistantNodes[i]));
|
|
40391
|
+
if (n === null)
|
|
40392
|
+
continue;
|
|
40393
|
+
if (n <= requestTurn)
|
|
40394
|
+
break;
|
|
40395
|
+
toEmit.push(assistantNodes[i]);
|
|
40396
|
+
}
|
|
40397
|
+
// emit in chronological order (reverse of collection order)
|
|
40398
|
+
for (let i = toEmit.length - 1; i >= 0; i--) {
|
|
40399
|
+
this.handleAssistantMessage(this.dom(toEmit[i]));
|
|
40400
|
+
}
|
|
40401
|
+
}
|
|
40402
|
+
extractContent(node) {
|
|
40403
|
+
const rawContent = node.text().trim();
|
|
40404
|
+
const content = this.applyPrivacyFilter(rawContent);
|
|
40405
|
+
return { content, privacyFilterApplied: content !== rawContent };
|
|
40406
|
+
}
|
|
40407
|
+
getMessageId(node) {
|
|
40408
|
+
return node.attr(this.findSelector(MESSAGE_ID_ATTR));
|
|
40409
|
+
}
|
|
40410
|
+
handleUserMessage(node) {
|
|
40411
|
+
this.emit('prompt', Object.assign({ agentId: this.id, messageId: this.getMessageId(node) }, this.extractContent(node)));
|
|
40412
|
+
}
|
|
40413
|
+
handleAssistantMessage(node) {
|
|
40414
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
40415
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
40416
|
+
this.emit('agent_response', Object.assign({ agentId: this.id, messageId: this.getMessageId(node), agentModelsUsed: modelUsed ? [modelUsed] : [] }, this.extractContent(node)));
|
|
40417
|
+
}
|
|
40418
|
+
findLastRequestNode() {
|
|
40419
|
+
if (!this.getConversationId())
|
|
40420
|
+
return null;
|
|
40421
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
40422
|
+
if (!node)
|
|
40423
|
+
return null;
|
|
40424
|
+
const $node = this.dom(node);
|
|
40425
|
+
const messageId = this.getMessageId($node);
|
|
40426
|
+
if (!messageId)
|
|
40427
|
+
return null;
|
|
40428
|
+
if (messageId === this.lastReturnedMessageId)
|
|
40429
|
+
return null;
|
|
40430
|
+
this.lastReturnedMessageId = messageId;
|
|
40431
|
+
return $node;
|
|
40432
|
+
}
|
|
40433
|
+
findTurnNumber(node) {
|
|
40434
|
+
const turnSelector = this.findSelector(TURN_CONTAINER);
|
|
40435
|
+
const turnAttr = this.findSelector(TURN_ATTR);
|
|
40436
|
+
const turn = node.closest(turnSelector).attr(turnAttr);
|
|
40437
|
+
if (!turn)
|
|
40438
|
+
return null;
|
|
40439
|
+
const seqMatch = String(turn).match(/\d+/);
|
|
40440
|
+
return seqMatch ? parseInt(seqMatch[0], 10) : null;
|
|
40441
|
+
}
|
|
40442
|
+
findSelector(type) {
|
|
40443
|
+
return this.selectors[type];
|
|
40444
|
+
}
|
|
40445
|
+
select(type) {
|
|
40446
|
+
return this.dom(this.findSelector(type), this.root);
|
|
40447
|
+
}
|
|
40448
|
+
getConversationId() {
|
|
40449
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
40450
|
+
if (!m)
|
|
40451
|
+
return null;
|
|
40452
|
+
return m[1] !== undefined ? m[1] : m[0];
|
|
40453
|
+
}
|
|
40454
|
+
getCustomAgentId() {
|
|
40455
|
+
if (!this.customAgentIdRegex)
|
|
40456
|
+
return undefined;
|
|
40457
|
+
const m = location.href.match(this.customAgentIdRegex);
|
|
40458
|
+
if (!m)
|
|
40459
|
+
return undefined;
|
|
40460
|
+
return m[1] !== undefined ? m[1] : m[0];
|
|
40461
|
+
}
|
|
40462
|
+
getCustomAgentName() {
|
|
40463
|
+
if (!this.findSelector(CUSTOM_AGENT_NAME))
|
|
40464
|
+
return '';
|
|
40465
|
+
const node = this.select(CUSTOM_AGENT_NAME);
|
|
40466
|
+
if (!node.length)
|
|
40467
|
+
return '';
|
|
40468
|
+
return node.text().trim();
|
|
40469
|
+
}
|
|
40470
|
+
addCustomAgentInfo(eventPayload) {
|
|
40471
|
+
const customAgentId = this.getCustomAgentId();
|
|
40472
|
+
if (!customAgentId)
|
|
40473
|
+
return;
|
|
40474
|
+
eventPayload.customAgentId = customAgentId;
|
|
40475
|
+
const customAgentName = this.getCustomAgentName();
|
|
40476
|
+
if (customAgentName) {
|
|
40477
|
+
eventPayload.customAgentName = customAgentName;
|
|
40478
|
+
}
|
|
40479
|
+
}
|
|
40480
|
+
setFilters(candidateFilter) {
|
|
40481
|
+
if (!candidateFilter) {
|
|
40482
|
+
this.privacyFilters = null;
|
|
40483
|
+
return null;
|
|
40484
|
+
}
|
|
40485
|
+
try {
|
|
40486
|
+
this.privacyFilters = new RegExp(candidateFilter, 'gmi');
|
|
40487
|
+
}
|
|
40488
|
+
catch (e) {
|
|
40489
|
+
this.privacyFilters = null;
|
|
40490
|
+
this.api.log.error(e);
|
|
40491
|
+
}
|
|
40492
|
+
return this.privacyFilters;
|
|
40493
|
+
}
|
|
40494
|
+
applyPrivacyFilter(candidateValue, filters = null) {
|
|
40495
|
+
const filtersToUse = filters || this.privacyFilters;
|
|
40496
|
+
if (!filtersToUse || !this._.isRegExp(filtersToUse))
|
|
40497
|
+
return candidateValue;
|
|
40498
|
+
return candidateValue.replace(filtersToUse, 'redacted');
|
|
40499
|
+
}
|
|
40500
|
+
onSubmit(callback) {
|
|
40501
|
+
this.listeners.push(callback);
|
|
40502
|
+
}
|
|
40503
|
+
emit(eventType, eventPayload) {
|
|
40504
|
+
eventPayload.conversationId = this.getConversationId();
|
|
40505
|
+
this.addCustomAgentInfo(eventPayload);
|
|
40506
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
40507
|
+
}
|
|
40508
|
+
startStreamingEndTimer() {
|
|
40509
|
+
this.stopStreamingEndTimer();
|
|
40510
|
+
this.streamingEndTimer = setTimeout$1(() => {
|
|
40511
|
+
this.streamingEndTimer = null;
|
|
40512
|
+
this.onSubmissionEnd();
|
|
40513
|
+
}, STREAMING_END_SETTLE_MS);
|
|
40514
|
+
}
|
|
40515
|
+
stopStreamingEndTimer() {
|
|
40516
|
+
if (!this.streamingEndTimer)
|
|
40517
|
+
return;
|
|
40518
|
+
clearTimeout(this.streamingEndTimer);
|
|
40519
|
+
this.streamingEndTimer = null;
|
|
40520
|
+
}
|
|
40521
|
+
startSubmissionStartRetryTimer(attempt) {
|
|
40522
|
+
this.stopSubmissionStartRetryTimer();
|
|
40523
|
+
this.submissionStartRetryTimer = setTimeout$1(() => {
|
|
40524
|
+
this.submissionStartRetryTimer = null;
|
|
40525
|
+
this.onSubmissionStart(attempt);
|
|
40526
|
+
}, SUBMISSION_START_RETRY_MS);
|
|
40527
|
+
}
|
|
40528
|
+
stopSubmissionStartRetryTimer() {
|
|
40529
|
+
if (!this.submissionStartRetryTimer)
|
|
40530
|
+
return;
|
|
40531
|
+
clearTimeout(this.submissionStartRetryTimer);
|
|
40532
|
+
this.submissionStartRetryTimer = null;
|
|
40533
|
+
}
|
|
40534
|
+
suspend() {
|
|
40535
|
+
this.isActive = false;
|
|
40536
|
+
}
|
|
40537
|
+
resume() {
|
|
40538
|
+
this.isActive = true;
|
|
40539
|
+
}
|
|
40540
|
+
teardown() {
|
|
40541
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
40542
|
+
this.observers = [];
|
|
40543
|
+
if (this.reactionClickHandler && this.root) {
|
|
40544
|
+
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
40545
|
+
this.reactionClickHandler = null;
|
|
40546
|
+
}
|
|
40547
|
+
this.stopStreamingEndTimer();
|
|
40548
|
+
this.stopSubmissionStartRetryTimer();
|
|
40549
|
+
this.listeners = [];
|
|
40550
|
+
}
|
|
40551
|
+
}
|
|
40552
|
+
|
|
39975
40553
|
/*
|
|
39976
40554
|
* Prompt Analytics Plugin
|
|
39977
40555
|
*
|
|
@@ -40136,18 +40714,31 @@ class PromptPlugin {
|
|
|
40136
40714
|
}
|
|
40137
40715
|
}
|
|
40138
40716
|
observePrompt(config) {
|
|
40139
|
-
const { id, cssSelectors, privacyFilters } = config;
|
|
40717
|
+
const { id, cssSelectors, privacyFilters, preset } = config;
|
|
40140
40718
|
// Check if agent already exists
|
|
40141
40719
|
const existingPrompt = this._.find(this.prompts, prompt => prompt.id === id);
|
|
40142
40720
|
if (existingPrompt) {
|
|
40143
40721
|
return;
|
|
40144
40722
|
}
|
|
40723
|
+
if (DOMConversation.supportedPreset(preset)) {
|
|
40724
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
40725
|
+
if (missing.length) {
|
|
40726
|
+
this.api.log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
40727
|
+
return;
|
|
40728
|
+
}
|
|
40729
|
+
const conversation = new DOMConversation(this.pendo, this.api, id, privacyFilters, cssSelectors);
|
|
40730
|
+
conversation.onSubmit((eventType, payload) => {
|
|
40731
|
+
this.sendConversationEvent(eventType, payload);
|
|
40732
|
+
});
|
|
40733
|
+
this.prompts.push(conversation);
|
|
40734
|
+
return;
|
|
40735
|
+
}
|
|
40145
40736
|
let inputCssSelectors, submitCssSelectors;
|
|
40146
40737
|
inputCssSelectors = this.parseCssSelector('input', cssSelectors);
|
|
40147
40738
|
submitCssSelectors = this.parseCssSelector('submit', cssSelectors);
|
|
40148
40739
|
const prompt = new DOMPrompt(this.pendo, this.api, id, privacyFilters, inputCssSelectors, submitCssSelectors);
|
|
40149
40740
|
prompt.onSubmit((promptPayload) => {
|
|
40150
|
-
this.
|
|
40741
|
+
this.sendPromptEvent(promptPayload);
|
|
40151
40742
|
});
|
|
40152
40743
|
this.prompts.push(prompt);
|
|
40153
40744
|
}
|
|
@@ -40156,7 +40747,7 @@ class PromptPlugin {
|
|
|
40156
40747
|
const selectors = this._.map(filtered, cfg => cfg.cssSelector);
|
|
40157
40748
|
return selectors;
|
|
40158
40749
|
}
|
|
40159
|
-
|
|
40750
|
+
sendPromptEvent(promptEvent) {
|
|
40160
40751
|
// Block event if the prompt is suspended
|
|
40161
40752
|
const prompt = this._.find(this.prompts, p => p.id === promptEvent.agentId);
|
|
40162
40753
|
if (prompt && !prompt.isActive) {
|
|
@@ -40168,6 +40759,15 @@ class PromptPlugin {
|
|
|
40168
40759
|
}, promptEvent);
|
|
40169
40760
|
this.api.analytics.collectEvent('prompt', event, undefined, 'agentic');
|
|
40170
40761
|
}
|
|
40762
|
+
sendConversationEvent(eventType, eventPayload) {
|
|
40763
|
+
// Block event if the prompt is suspended
|
|
40764
|
+
const conv = this._.find(this.prompts, p => p.id === eventPayload.agentId);
|
|
40765
|
+
if (conv && !conv.isActive) {
|
|
40766
|
+
return;
|
|
40767
|
+
}
|
|
40768
|
+
eventPayload = this._.extend({ agentType: 'conversation' }, eventPayload);
|
|
40769
|
+
this.api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
40770
|
+
}
|
|
40171
40771
|
teardown() {
|
|
40172
40772
|
this._.each(this.prompts, (prompt) => prompt.teardown());
|
|
40173
40773
|
if (this.agentsCache) {
|
|
@@ -40235,7 +40835,7 @@ class SessionManager {
|
|
|
40235
40835
|
this.suffix = this.api.ConfigReader.get('identityStorageSuffix');
|
|
40236
40836
|
/**
|
|
40237
40837
|
* Randomly generated string that identifies a session. This is similar to `pendo_tabId`,
|
|
40238
|
-
* but identifies the entire browser
|
|
40838
|
+
* but identifies the entire browser session rather than individual tabs.
|
|
40239
40839
|
*
|
|
40240
40840
|
* @name sessionId
|
|
40241
40841
|
* @category Cookies/localStorage
|
|
@@ -40734,6 +41334,7 @@ function registerBuiltInPlugins() {
|
|
|
40734
41334
|
registerPlugin(EventProperties);
|
|
40735
41335
|
registerPlugin(FormValidation);
|
|
40736
41336
|
registerPlugin(FrustrationEvent);
|
|
41337
|
+
registerPlugin(GuideCachePlugin);
|
|
40737
41338
|
registerPlugin(IFrameMonitor);
|
|
40738
41339
|
registerPlugin(OemAccountId);
|
|
40739
41340
|
registerPlugin(P1GuidePlugin);
|
|
@@ -40988,20 +41589,20 @@ function getZoneSafeMethod(_, method, target) {
|
|
|
40988
41589
|
}
|
|
40989
41590
|
|
|
40990
41591
|
// Does not support submit and go to
|
|
40991
|
-
|
|
40992
|
-
|
|
41592
|
+
var goToRegex = new RegExp(guideMarkdownUtil.goToString);
|
|
41593
|
+
var PollBranching = {
|
|
40993
41594
|
name: 'PollBranching',
|
|
40994
|
-
script(step, guide, pendo) {
|
|
40995
|
-
|
|
40996
|
-
|
|
41595
|
+
script: function (step, guide, pendo) {
|
|
41596
|
+
var isAdvanceIntercepted = false;
|
|
41597
|
+
var branchingQuestions = initialBranchingSetup(step, pendo);
|
|
40997
41598
|
if (branchingQuestions) {
|
|
40998
41599
|
// If there are too many branching questions saved, exit and run the guide normally.
|
|
40999
41600
|
if (pendo._.size(branchingQuestions) > 1)
|
|
41000
41601
|
return;
|
|
41001
|
-
this.on('beforeAdvance', (evt)
|
|
41002
|
-
|
|
41003
|
-
|
|
41004
|
-
|
|
41602
|
+
this.on('beforeAdvance', function (evt) {
|
|
41603
|
+
var noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
|
|
41604
|
+
var responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
|
|
41605
|
+
var noGotoLabel;
|
|
41005
41606
|
if (responseLabel) {
|
|
41006
41607
|
noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
|
|
41007
41608
|
}
|
|
@@ -41012,58 +41613,58 @@ const PollBranching = {
|
|
|
41012
41613
|
});
|
|
41013
41614
|
}
|
|
41014
41615
|
},
|
|
41015
|
-
test(step, guide, pendo) {
|
|
41616
|
+
test: function (step, guide, pendo) {
|
|
41016
41617
|
var _a;
|
|
41017
|
-
|
|
41618
|
+
var branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41018
41619
|
return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
|
|
41019
41620
|
},
|
|
41020
|
-
designerListener(pendo) {
|
|
41021
|
-
|
|
41022
|
-
|
|
41621
|
+
designerListener: function (pendo) {
|
|
41622
|
+
var target = pendo.dom.getBody();
|
|
41623
|
+
var config = {
|
|
41023
41624
|
attributeFilter: ['data-layout'],
|
|
41024
41625
|
attributes: true,
|
|
41025
41626
|
childList: true,
|
|
41026
41627
|
characterData: true,
|
|
41027
41628
|
subtree: true
|
|
41028
41629
|
};
|
|
41029
|
-
|
|
41030
|
-
|
|
41630
|
+
var MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41631
|
+
var observer = new MutationObserver(applyBranchingIndicators);
|
|
41031
41632
|
observer.observe(target, config);
|
|
41032
41633
|
function applyBranchingIndicators(mutations) {
|
|
41033
41634
|
pendo._.each(mutations, function (mutation) {
|
|
41034
41635
|
var _a;
|
|
41035
|
-
|
|
41636
|
+
var nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
|
|
41036
41637
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41037
41638
|
if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
|
|
41038
41639
|
if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
|
|
41039
41640
|
pendo
|
|
41040
41641
|
.dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
|
|
41041
|
-
.each((question, index)
|
|
41042
|
-
pendo._.each(pendo.dom(
|
|
41642
|
+
.each(function (question, index) {
|
|
41643
|
+
pendo._.each(pendo.dom("#".concat(question.id, " *")), function (element) {
|
|
41043
41644
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41044
41645
|
});
|
|
41045
41646
|
pendo
|
|
41046
|
-
.dom(
|
|
41647
|
+
.dom("#".concat(question.id, " p"))
|
|
41047
41648
|
.css({ display: 'inline-block !important' })
|
|
41048
41649
|
.append(branchingIcon('#999', '20px'))
|
|
41049
41650
|
.attr({ title: 'Custom Branching Added' });
|
|
41050
|
-
|
|
41051
|
-
if (pendo.dom(
|
|
41651
|
+
var dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41652
|
+
if (pendo.dom("._pendo-multi-choice-poll-question[data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0]) {
|
|
41052
41653
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41053
41654
|
pendo
|
|
41054
|
-
.dom(
|
|
41655
|
+
.dom("._pendo-multi-choice-poll-question[data-pendo-poll-id=".concat(dataPendoPollId, "]"))[0]
|
|
41055
41656
|
.textContent.trim();
|
|
41056
41657
|
}
|
|
41057
|
-
|
|
41658
|
+
var pollLabels = pendo.dom("label[for*=".concat(dataPendoPollId, "]"));
|
|
41058
41659
|
if (pendo._.size(pollLabels)) {
|
|
41059
|
-
pendo._.forEach(pollLabels, (label)
|
|
41660
|
+
pendo._.forEach(pollLabels, function (label) {
|
|
41060
41661
|
if (goToRegex.test(label.textContent)) {
|
|
41061
|
-
|
|
41662
|
+
var labelTitle = goToRegex.exec(label.textContent)[2];
|
|
41062
41663
|
guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
|
|
41063
41664
|
pendo
|
|
41064
41665
|
.dom(label)
|
|
41065
41666
|
.append(branchingIcon('#999', '14px'))
|
|
41066
|
-
.attr({ title:
|
|
41667
|
+
.attr({ title: "Branching to step ".concat(labelTitle) });
|
|
41067
41668
|
}
|
|
41068
41669
|
});
|
|
41069
41670
|
}
|
|
@@ -41071,9 +41672,9 @@ const PollBranching = {
|
|
|
41071
41672
|
pendo
|
|
41072
41673
|
.dom(question)
|
|
41073
41674
|
.append(branchingErrorHTML(question.dataset.pendoPollId));
|
|
41074
|
-
pendo.dom(
|
|
41675
|
+
pendo.dom("#".concat(question.id, " #pendo-ps-branching-svg")).remove();
|
|
41075
41676
|
pendo
|
|
41076
|
-
.dom(
|
|
41677
|
+
.dom("#".concat(question.id, " p"))
|
|
41077
41678
|
.css({ display: 'inline-block !important' })
|
|
41078
41679
|
.append(branchingIcon('red', '20px'))
|
|
41079
41680
|
.attr({ title: 'Unsupported Branching configuration' });
|
|
@@ -41085,49 +41686,31 @@ const PollBranching = {
|
|
|
41085
41686
|
});
|
|
41086
41687
|
}
|
|
41087
41688
|
function branchingErrorHTML(dataPendoPollId) {
|
|
41088
|
-
return
|
|
41089
|
-
font-style: italic; margin-top: 0px;" class="branching-wrapper"
|
|
41090
|
-
name="${dataPendoPollId}">
|
|
41091
|
-
* Branching Error: Multiple branching polls not supported</div>`;
|
|
41689
|
+
return "<div style=\"text-align:lrft; font-size: 14px; color: red;\n font-style: italic; margin-top: 0px;\" class=\"branching-wrapper\"\n name=\"".concat(dataPendoPollId, "\">\n * Branching Error: Multiple branching polls not supported</div>");
|
|
41092
41690
|
}
|
|
41093
41691
|
function branchingIcon(color, size) {
|
|
41094
|
-
return
|
|
41095
|
-
style="margin-left: 5px;
|
|
41096
|
-
height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
|
|
41097
|
-
<g stroke-width="0"></g>
|
|
41098
|
-
<g stroke-linecap="round" stroke-linejoin="round"></g>
|
|
41099
|
-
<g> <circle cx="4" cy="7" r="2" stroke="${color}"
|
|
41100
|
-
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41101
|
-
<circle cx="20" cy="7" r="2" stroke="${color}"
|
|
41102
|
-
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41103
|
-
<circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
|
|
41104
|
-
stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41105
|
-
<path d="M18 7H6" stroke="${color}" stroke-width="2"
|
|
41106
|
-
stroke-linecap="round" stroke-linejoin="round"></path>
|
|
41107
|
-
<path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
|
|
41108
|
-
stroke="${color}" stroke-width="2" stroke-linecap="round"
|
|
41109
|
-
stroke-linejoin="round"></path> </g></svg>`;
|
|
41692
|
+
return "<svg id=\"pendo-ps-branching-svg\" viewBox=\"0 0 24 24\" fill=\"none\"\n style=\"margin-left: 5px;\n height:".concat(size, "; width:").concat(size, "; display:inline; vertical-align:middle;\" xmlns=\"http://www.w3.org/2000/svg\">\n <g stroke-width=\"0\"></g>\n <g stroke-linecap=\"round\" stroke-linejoin=\"round\"></g>\n <g> <circle cx=\"4\" cy=\"7\" r=\"2\" stroke=\"").concat(color, "\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <circle cx=\"20\" cy=\"7\" r=\"2\" stroke=\"").concat(color, "\"\n stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <circle cx=\"20\" cy=\"17\" r=\"2\" stroke=\"").concat(color, "\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"></circle>\n <path d=\"M18 7H6\" stroke=\"").concat(color, "\" stroke-width=\"2\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18\"\n stroke=\"").concat(color, "\" stroke-width=\"2\" stroke-linecap=\"round\"\n stroke-linejoin=\"round\"></path> </g></svg>");
|
|
41110
41693
|
}
|
|
41111
41694
|
}
|
|
41112
41695
|
};
|
|
41113
41696
|
function initialBranchingSetup(step, pendo) {
|
|
41114
|
-
|
|
41115
|
-
pendo._.forEach(questions, (question)
|
|
41116
|
-
|
|
41117
|
-
pendo._.each(step.guideElement.find(
|
|
41697
|
+
var questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41698
|
+
pendo._.forEach(questions, function (question) {
|
|
41699
|
+
var dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41700
|
+
pendo._.each(step.guideElement.find("#".concat(question.id, " *")), function (element) {
|
|
41118
41701
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41119
41702
|
});
|
|
41120
|
-
|
|
41121
|
-
pendo._.forEach(pollLabels, (label)
|
|
41703
|
+
var pollLabels = step.guideElement.find("label[for*=".concat(dataPendoPollId, "]"));
|
|
41704
|
+
pendo._.forEach(pollLabels, function (label) {
|
|
41122
41705
|
if (pendo._.isNull(goToRegex.exec(label.textContent))) {
|
|
41123
41706
|
return;
|
|
41124
41707
|
}
|
|
41125
|
-
|
|
41126
|
-
|
|
41708
|
+
var gotoSubstring = goToRegex.exec(label.textContent)[1];
|
|
41709
|
+
var gotoIndex = goToRegex.exec(label.textContent)[2];
|
|
41127
41710
|
label.setAttribute('goToStep', gotoIndex);
|
|
41128
41711
|
guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
|
|
41129
41712
|
});
|
|
41130
|
-
|
|
41713
|
+
var pollChoiceContainer = step.guideElement.find("[data-pendo-poll-id=".concat(dataPendoPollId, "]._pendo-multi-choice-poll-select-border"));
|
|
41131
41714
|
if (pollChoiceContainer && pollChoiceContainer.length) {
|
|
41132
41715
|
pollChoiceContainer[0].setAttribute('branching', '');
|
|
41133
41716
|
}
|
|
@@ -41136,15 +41719,15 @@ function initialBranchingSetup(step, pendo) {
|
|
|
41136
41719
|
}
|
|
41137
41720
|
function branchingGoToStep(event, step, guide, pendo) {
|
|
41138
41721
|
var _a;
|
|
41139
|
-
|
|
41140
|
-
|
|
41141
|
-
|
|
41142
|
-
|
|
41722
|
+
var checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
41723
|
+
var checkedPollLabel = step.guideElement.find("label[for=\"".concat(checkedPollInputId, "\"]"))[0];
|
|
41724
|
+
var checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
|
|
41725
|
+
var pollStepIndex = checkedPollLabelStepIndex - 1;
|
|
41143
41726
|
if (pollStepIndex < 0)
|
|
41144
41727
|
return;
|
|
41145
|
-
|
|
41728
|
+
var destinationObject = {
|
|
41146
41729
|
destinationStepId: guide.steps[pollStepIndex].id,
|
|
41147
|
-
step
|
|
41730
|
+
step: step
|
|
41148
41731
|
};
|
|
41149
41732
|
pendo.goToStep(destinationObject);
|
|
41150
41733
|
event.cancel = true;
|
|
@@ -41460,7 +42043,10 @@ const RequiredQuestions = {
|
|
|
41460
42043
|
});
|
|
41461
42044
|
}
|
|
41462
42045
|
function getEligibleQuestions() {
|
|
41463
|
-
const
|
|
42046
|
+
const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
|
|
42047
|
+
const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
|
|
42048
|
+
const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
|
|
42049
|
+
const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
41464
42050
|
return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
|
|
41465
42051
|
if (question.classList.contains('_pendo-yes-no-poll-question'))
|
|
41466
42052
|
return eligibleQuestions;
|
|
@@ -41468,16 +42054,30 @@ const RequiredQuestions = {
|
|
|
41468
42054
|
return eligibleQuestions;
|
|
41469
42055
|
}, []);
|
|
41470
42056
|
}
|
|
42057
|
+
function ownsRequiredText(element) {
|
|
42058
|
+
return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
|
|
42059
|
+
}
|
|
41471
42060
|
function processRequiredQuestions() {
|
|
41472
42061
|
let questions = getEligibleQuestions();
|
|
41473
42062
|
if (questions) {
|
|
41474
42063
|
pendo._.forEach(questions, question => {
|
|
41475
42064
|
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41476
42065
|
requiredPollIds.push(dataPendoPollId);
|
|
41477
|
-
|
|
42066
|
+
const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
|
|
42067
|
+
const textHost = pendo._.find(candidates, ownsRequiredText) || question;
|
|
42068
|
+
pendo._.each(candidates, (element) => {
|
|
41478
42069
|
guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
|
|
41479
42070
|
});
|
|
41480
|
-
|
|
42071
|
+
const textHostEl = pendo.dom(textHost);
|
|
42072
|
+
if (textHostEl.find('._pendo-required-indicator').length === 0) {
|
|
42073
|
+
const questionParagraph = textHostEl.find('p');
|
|
42074
|
+
if (questionParagraph && questionParagraph.length) {
|
|
42075
|
+
pendo.dom(questionParagraph[0]).append(requiredElement);
|
|
42076
|
+
}
|
|
42077
|
+
else {
|
|
42078
|
+
textHostEl.append(requiredElement);
|
|
42079
|
+
}
|
|
42080
|
+
}
|
|
41481
42081
|
});
|
|
41482
42082
|
}
|
|
41483
42083
|
if (pendo._.size(requiredPollIds)) {
|
|
@@ -41541,9 +42141,11 @@ const RequiredQuestions = {
|
|
|
41541
42141
|
}
|
|
41542
42142
|
},
|
|
41543
42143
|
test(step, guide, pendo) {
|
|
41544
|
-
var _a;
|
|
41545
|
-
|
|
41546
|
-
|
|
42144
|
+
var _a, _b;
|
|
42145
|
+
const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
|
|
42146
|
+
const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
|
|
42147
|
+
return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
|
|
42148
|
+
(!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
|
|
41547
42149
|
},
|
|
41548
42150
|
designerListener(pendo) {
|
|
41549
42151
|
const requiredQuestions = [];
|
|
@@ -41563,7 +42165,7 @@ const RequiredQuestions = {
|
|
|
41563
42165
|
var _a;
|
|
41564
42166
|
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
41565
42167
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41566
|
-
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border]');
|
|
42168
|
+
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
|
|
41567
42169
|
if (eligiblePolls) {
|
|
41568
42170
|
pendo._.each(eligiblePolls, function (poll) {
|
|
41569
42171
|
let dataPendoPollId;
|
|
@@ -41575,11 +42177,12 @@ const RequiredQuestions = {
|
|
|
41575
42177
|
dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
|
|
41576
42178
|
}
|
|
41577
42179
|
let questionText;
|
|
41578
|
-
const
|
|
41579
|
-
|
|
41580
|
-
|
|
42180
|
+
const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
|
|
42181
|
+
pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
|
|
42182
|
+
if (questionElement) {
|
|
42183
|
+
questionText = questionElement.textContent;
|
|
41581
42184
|
}
|
|
41582
|
-
const requiredSyntaxIndex = questionText.indexOf(requiredSyntax);
|
|
42185
|
+
const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
|
|
41583
42186
|
if (requiredSyntaxIndex > -1) {
|
|
41584
42187
|
pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
|
|
41585
42188
|
pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
|
|
@@ -49093,6 +49696,17 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49093
49696
|
return SessionRecorderBuffer;
|
|
49094
49697
|
}());
|
|
49095
49698
|
|
|
49699
|
+
var __assign = function() {
|
|
49700
|
+
__assign = Object.assign || function __assign(t) {
|
|
49701
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
49702
|
+
s = arguments[i];
|
|
49703
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
49704
|
+
}
|
|
49705
|
+
return t;
|
|
49706
|
+
};
|
|
49707
|
+
return __assign.apply(this, arguments);
|
|
49708
|
+
};
|
|
49709
|
+
|
|
49096
49710
|
function __rest(s, e) {
|
|
49097
49711
|
var t = {};
|
|
49098
49712
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -49325,6 +49939,8 @@ function shouldMask(node, options) {
|
|
|
49325
49939
|
var el = isElementNode(node) ? node : node.parentElement;
|
|
49326
49940
|
if (el === null)
|
|
49327
49941
|
return false;
|
|
49942
|
+
if ((el.tagName || '').toUpperCase() === 'STYLE')
|
|
49943
|
+
return false;
|
|
49328
49944
|
var maskDistance = -1;
|
|
49329
49945
|
var unmaskDistance = -1;
|
|
49330
49946
|
if (maskAllText) {
|
|
@@ -49467,7 +50083,7 @@ class SessionRecorder {
|
|
|
49467
50083
|
// https://github.com/pendo-io/pendo-browser-extension/blob/master/src/common/agent-loader.js
|
|
49468
50084
|
cf.addOption(RECORDING_CONFIG_ON_RECORDING_STOP, [cf.sources.SNIPPET_SRC, cf.sources.PENDO_CONFIG_SRC], undefined);
|
|
49469
50085
|
/**
|
|
49470
|
-
* Used when self
|
|
50086
|
+
* Used when self-hosting the replay web worker. Specifies the URL that points to the self-hosted web worker.
|
|
49471
50087
|
*
|
|
49472
50088
|
* @access public
|
|
49473
50089
|
* @category Config/Replay
|
|
@@ -49575,7 +50191,7 @@ class SessionRecorder {
|
|
|
49575
50191
|
this.subscriptions.push(this.api.attachEvent(this.api.Events, 'ready', bind(this.ready, this)));
|
|
49576
50192
|
}
|
|
49577
50193
|
/**
|
|
49578
|
-
* Randomly generated string that identifies a session. This is
|
|
50194
|
+
* Randomly generated string that identifies a session. This is similar to `pendo_sessionId`, but
|
|
49579
50195
|
* meant specifically for session recording.
|
|
49580
50196
|
*
|
|
49581
50197
|
* @name pendo_srId
|
|
@@ -49740,6 +50356,7 @@ class SessionRecorder {
|
|
|
49740
50356
|
* Used to start collecting replay data.
|
|
49741
50357
|
*
|
|
49742
50358
|
* @function start
|
|
50359
|
+
* @alias recording.start
|
|
49743
50360
|
* @category Replay
|
|
49744
50361
|
* @access public
|
|
49745
50362
|
* @example
|
|
@@ -51254,7 +51871,7 @@ function includes(str, substring) {
|
|
|
51254
51871
|
function getResourceType(blockedURI, directive) {
|
|
51255
51872
|
if (!directive || typeof directive !== 'string')
|
|
51256
51873
|
return 'resource';
|
|
51257
|
-
|
|
51874
|
+
var d = directive.toLowerCase();
|
|
51258
51875
|
if (blockedURI === 'inline') {
|
|
51259
51876
|
if (includes(d, 'script-src-attr')) {
|
|
51260
51877
|
return 'inline event handler';
|
|
@@ -51313,11 +51930,12 @@ function getResourceType(blockedURI, directive) {
|
|
|
51313
51930
|
function getDirective(policy, directiveName) {
|
|
51314
51931
|
if (!policy || !directiveName)
|
|
51315
51932
|
return '';
|
|
51316
|
-
|
|
51317
|
-
for (
|
|
51318
|
-
|
|
51319
|
-
|
|
51320
|
-
|
|
51933
|
+
var needle = directiveName.toLowerCase();
|
|
51934
|
+
for (var _i = 0, _a = policy.split(';'); _i < _a.length; _i++) {
|
|
51935
|
+
var directive = _a[_i];
|
|
51936
|
+
var trimmed = directive.trim();
|
|
51937
|
+
var lower = trimmed.toLowerCase();
|
|
51938
|
+
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
51321
51939
|
return trimmed;
|
|
51322
51940
|
}
|
|
51323
51941
|
}
|
|
@@ -51339,7 +51957,7 @@ function getDirective(policy, directiveName) {
|
|
|
51339
51957
|
function getArticle(phrase) {
|
|
51340
51958
|
if (!phrase || typeof phrase !== 'string')
|
|
51341
51959
|
return 'A';
|
|
51342
|
-
|
|
51960
|
+
var c = phrase.trim().charAt(0).toLowerCase();
|
|
51343
51961
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
51344
51962
|
}
|
|
51345
51963
|
/**
|
|
@@ -51382,46 +52000,47 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
51382
52000
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
51383
52001
|
}
|
|
51384
52002
|
try {
|
|
51385
|
-
|
|
52003
|
+
var reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
51386
52004
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
51387
52005
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
51388
|
-
return
|
|
52006
|
+
return "Content Security Policy".concat(reportOnlyText, ": The display of ").concat(blockedURI, " in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: \"").concat(originalPolicy, "\".");
|
|
51389
52007
|
}
|
|
51390
|
-
|
|
51391
|
-
|
|
51392
|
-
|
|
51393
|
-
|
|
51394
|
-
|
|
51395
|
-
|
|
51396
|
-
return
|
|
52008
|
+
var resourceType = getResourceType(blockedURI, directive);
|
|
52009
|
+
var article = getArticle(resourceType);
|
|
52010
|
+
var source = formatBlockedUri(blockedURI);
|
|
52011
|
+
var directiveValue = getDirective(originalPolicy, directive);
|
|
52012
|
+
var policyDisplay = directiveValue || directive;
|
|
52013
|
+
var resourceDescription = "".concat(article, " ").concat(resourceType).concat(source ? " from ".concat(source) : '');
|
|
52014
|
+
return "Content Security Policy".concat(reportOnlyText, ": ").concat(resourceDescription, " was blocked by your site's `").concat(policyDisplay, "` policy.\nCurrent CSP: \"").concat(originalPolicy, "\".");
|
|
51397
52015
|
}
|
|
51398
52016
|
catch (error) {
|
|
51399
|
-
return
|
|
52017
|
+
return "Content Security Policy: Error formatting violation message: ".concat(error.message);
|
|
51400
52018
|
}
|
|
51401
52019
|
}
|
|
51402
52020
|
|
|
51403
|
-
|
|
51404
|
-
|
|
52021
|
+
var MAX_LENGTH = 1000;
|
|
52022
|
+
var PII_PATTERN = {
|
|
51405
52023
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
51406
52024
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
51407
52025
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
51408
52026
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
51409
52027
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
51410
52028
|
};
|
|
51411
|
-
|
|
51412
|
-
|
|
51413
|
-
|
|
51414
|
-
|
|
51415
|
-
|
|
52029
|
+
var PII_REPLACEMENT = '*'.repeat(10);
|
|
52030
|
+
var JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
52031
|
+
var UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
52032
|
+
var joinedKeys = JSON_PII_KEYS.join('|');
|
|
52033
|
+
var keyPattern = "\"([^\"]*(?:".concat(joinedKeys, ")[^\"]*)\"");
|
|
51416
52034
|
// only scrub strings, numbers, and booleans
|
|
51417
|
-
|
|
52035
|
+
var acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
51418
52036
|
/**
|
|
51419
52037
|
* Truncates a string to the max length
|
|
51420
52038
|
* @access private
|
|
51421
52039
|
* @param {String} string
|
|
51422
52040
|
* @returns {String}
|
|
51423
52041
|
*/
|
|
51424
|
-
function truncate(string, includeEllipsis
|
|
52042
|
+
function truncate(string, includeEllipsis) {
|
|
52043
|
+
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
51425
52044
|
if (string.length <= MAX_LENGTH)
|
|
51426
52045
|
return string;
|
|
51427
52046
|
if (includeEllipsis) {
|
|
@@ -51438,7 +52057,7 @@ function truncate(string, includeEllipsis = false) {
|
|
|
51438
52057
|
* @returns {String}
|
|
51439
52058
|
*/
|
|
51440
52059
|
function generateLogKey(methodName, message, stackTrace) {
|
|
51441
|
-
return
|
|
52060
|
+
return "".concat(methodName, "|").concat(message, "|").concat(stackTrace);
|
|
51442
52061
|
}
|
|
51443
52062
|
/**
|
|
51444
52063
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -51455,12 +52074,13 @@ function mightContainPII(string) {
|
|
|
51455
52074
|
* @param {String} string
|
|
51456
52075
|
* @returns {String}
|
|
51457
52076
|
*/
|
|
51458
|
-
function scrubPII(
|
|
52077
|
+
function scrubPII(_a) {
|
|
52078
|
+
var string = _a.string, _ = _a._;
|
|
51459
52079
|
if (!string || typeof string !== 'string')
|
|
51460
52080
|
return string;
|
|
51461
52081
|
if (!mightContainPII(string))
|
|
51462
52082
|
return string;
|
|
51463
|
-
return _.reduce(_.values(PII_PATTERN), (str, pattern)
|
|
52083
|
+
return _.reduce(_.values(PII_PATTERN), function (str, pattern) { return str.replace(pattern, PII_REPLACEMENT); }, string);
|
|
51464
52084
|
}
|
|
51465
52085
|
/**
|
|
51466
52086
|
* Scrub PII from a stringified JSON object
|
|
@@ -51469,12 +52089,14 @@ function scrubPII({ string, _ }) {
|
|
|
51469
52089
|
* @returns {String}
|
|
51470
52090
|
*/
|
|
51471
52091
|
function scrubJsonPII(string) {
|
|
51472
|
-
|
|
52092
|
+
var fullScrubRegex = new RegExp("".concat(keyPattern, "\\s*:\\s*[\\{\\[]"), 'i');
|
|
51473
52093
|
if (fullScrubRegex.test(string)) {
|
|
51474
52094
|
return UNABLE_TO_DISPLAY_BODY;
|
|
51475
52095
|
}
|
|
51476
|
-
|
|
51477
|
-
return string.replace(keyValueScrubRegex, (match, key)
|
|
52096
|
+
var keyValueScrubRegex = new RegExp("".concat(keyPattern, "\\s*:\\s*").concat(acceptedValues), 'gi');
|
|
52097
|
+
return string.replace(keyValueScrubRegex, function (match, key) {
|
|
52098
|
+
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
52099
|
+
});
|
|
51478
52100
|
}
|
|
51479
52101
|
/**
|
|
51480
52102
|
* Checks if a string is a JSON object
|
|
@@ -51486,7 +52108,7 @@ function scrubJsonPII(string) {
|
|
|
51486
52108
|
function mightContainJson(string, contentType) {
|
|
51487
52109
|
if (!string || typeof string !== 'string')
|
|
51488
52110
|
return false;
|
|
51489
|
-
|
|
52111
|
+
var firstChar = string.charAt(0);
|
|
51490
52112
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
51491
52113
|
return true;
|
|
51492
52114
|
}
|
|
@@ -51499,19 +52121,20 @@ function mightContainJson(string, contentType) {
|
|
|
51499
52121
|
* @param {String} contentType
|
|
51500
52122
|
* @returns {String}
|
|
51501
52123
|
*/
|
|
51502
|
-
function maskSensitiveFields(
|
|
52124
|
+
function maskSensitiveFields(_a) {
|
|
52125
|
+
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
51503
52126
|
if (!string || typeof string !== 'string')
|
|
51504
52127
|
return string;
|
|
51505
52128
|
if (mightContainJson(string, contentType)) {
|
|
51506
52129
|
string = scrubJsonPII(string);
|
|
51507
52130
|
}
|
|
51508
52131
|
if (mightContainPII(string)) {
|
|
51509
|
-
string = scrubPII({ string, _ });
|
|
52132
|
+
string = scrubPII({ string: string, _: _ });
|
|
51510
52133
|
}
|
|
51511
52134
|
return string;
|
|
51512
52135
|
}
|
|
51513
52136
|
|
|
51514
|
-
|
|
52137
|
+
var DEV_LOG_TYPE = 'devlog';
|
|
51515
52138
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
51516
52139
|
return {
|
|
51517
52140
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -51522,12 +52145,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
|
51522
52145
|
};
|
|
51523
52146
|
}
|
|
51524
52147
|
|
|
51525
|
-
|
|
51526
|
-
|
|
51527
|
-
|
|
51528
|
-
|
|
51529
|
-
|
|
51530
|
-
|
|
52148
|
+
var TOKEN_MAX_SIZE = 100;
|
|
52149
|
+
var TOKEN_REFILL_RATE = 10;
|
|
52150
|
+
var TOKEN_REFRESH_INTERVAL = 1000;
|
|
52151
|
+
var MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
|
|
52152
|
+
var DevlogBuffer = /** @class */ (function () {
|
|
52153
|
+
function DevlogBuffer(pendo, pluginAPI) {
|
|
51531
52154
|
this.pendo = pendo;
|
|
51532
52155
|
this.pluginAPI = pluginAPI;
|
|
51533
52156
|
this.events = [];
|
|
@@ -51538,36 +52161,36 @@ class DevlogBuffer {
|
|
|
51538
52161
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
51539
52162
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
51540
52163
|
}
|
|
51541
|
-
isEmpty() {
|
|
52164
|
+
DevlogBuffer.prototype.isEmpty = function () {
|
|
51542
52165
|
return this.events.length === 0 && this.payloads.length === 0;
|
|
51543
|
-
}
|
|
51544
|
-
refillTokens() {
|
|
51545
|
-
|
|
52166
|
+
};
|
|
52167
|
+
DevlogBuffer.prototype.refillTokens = function () {
|
|
52168
|
+
var now = this.pluginAPI.util.getNow();
|
|
51546
52169
|
if (now >= this.nextRefillTime) {
|
|
51547
|
-
|
|
51548
|
-
|
|
51549
|
-
|
|
52170
|
+
var timeSinceLastRefill = now - this.lastRefillTime;
|
|
52171
|
+
var secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
|
|
52172
|
+
var tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
|
|
51550
52173
|
this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
|
|
51551
52174
|
this.lastRefillTime = now;
|
|
51552
52175
|
this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
|
|
51553
52176
|
}
|
|
51554
|
-
}
|
|
51555
|
-
clear() {
|
|
52177
|
+
};
|
|
52178
|
+
DevlogBuffer.prototype.clear = function () {
|
|
51556
52179
|
this.events = [];
|
|
51557
52180
|
this.lastEvent = null;
|
|
51558
52181
|
this.uncompressedSize = 0;
|
|
51559
|
-
}
|
|
51560
|
-
hasTokenAvailable() {
|
|
52182
|
+
};
|
|
52183
|
+
DevlogBuffer.prototype.hasTokenAvailable = function () {
|
|
51561
52184
|
this.refillTokens();
|
|
51562
52185
|
return this.tokens > 0;
|
|
51563
|
-
}
|
|
51564
|
-
estimateEventSize(event) {
|
|
52186
|
+
};
|
|
52187
|
+
DevlogBuffer.prototype.estimateEventSize = function (event) {
|
|
51565
52188
|
return JSON.stringify(event).length;
|
|
51566
|
-
}
|
|
51567
|
-
push(event) {
|
|
52189
|
+
};
|
|
52190
|
+
DevlogBuffer.prototype.push = function (event) {
|
|
51568
52191
|
if (!this.hasTokenAvailable())
|
|
51569
52192
|
return false;
|
|
51570
|
-
|
|
52193
|
+
var eventSize = this.estimateEventSize(event);
|
|
51571
52194
|
if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
|
|
51572
52195
|
this.compressCurrentChunk();
|
|
51573
52196
|
}
|
|
@@ -51576,54 +52199,55 @@ class DevlogBuffer {
|
|
|
51576
52199
|
this.events.push(event);
|
|
51577
52200
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
51578
52201
|
return true;
|
|
51579
|
-
}
|
|
51580
|
-
compressCurrentChunk() {
|
|
52202
|
+
};
|
|
52203
|
+
DevlogBuffer.prototype.compressCurrentChunk = function () {
|
|
51581
52204
|
if (this.events.length === 0)
|
|
51582
52205
|
return;
|
|
51583
|
-
|
|
52206
|
+
var jzb = this.pendo.compress(this.events);
|
|
51584
52207
|
this.payloads.push(jzb);
|
|
51585
52208
|
this.clear();
|
|
51586
|
-
}
|
|
51587
|
-
generateUrl() {
|
|
51588
|
-
|
|
52209
|
+
};
|
|
52210
|
+
DevlogBuffer.prototype.generateUrl = function () {
|
|
52211
|
+
var queryParams = {
|
|
51589
52212
|
v: this.pendo.VERSION,
|
|
51590
52213
|
ct: this.pluginAPI.util.getNow()
|
|
51591
52214
|
};
|
|
51592
52215
|
return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
|
|
51593
|
-
}
|
|
51594
|
-
pack() {
|
|
52216
|
+
};
|
|
52217
|
+
DevlogBuffer.prototype.pack = function () {
|
|
51595
52218
|
if (this.isEmpty())
|
|
51596
52219
|
return;
|
|
51597
|
-
|
|
52220
|
+
var url = this.generateUrl();
|
|
51598
52221
|
this.compressCurrentChunk();
|
|
51599
|
-
|
|
51600
|
-
jzb,
|
|
51601
|
-
url
|
|
51602
|
-
}));
|
|
52222
|
+
var payloads = this.pendo._.map(this.payloads, function (jzb) { return ({
|
|
52223
|
+
jzb: jzb,
|
|
52224
|
+
url: url
|
|
52225
|
+
}); });
|
|
51603
52226
|
this.payloads = [];
|
|
51604
52227
|
return payloads;
|
|
51605
|
-
}
|
|
51606
|
-
|
|
52228
|
+
};
|
|
52229
|
+
return DevlogBuffer;
|
|
52230
|
+
}());
|
|
51607
52231
|
|
|
51608
|
-
|
|
51609
|
-
|
|
52232
|
+
var DevlogTransport = /** @class */ (function () {
|
|
52233
|
+
function DevlogTransport(globalPendo, pluginAPI) {
|
|
51610
52234
|
this.pendo = globalPendo;
|
|
51611
52235
|
this.pluginAPI = pluginAPI;
|
|
51612
52236
|
}
|
|
51613
|
-
buildGetUrl(baseUrl, jzb) {
|
|
51614
|
-
|
|
52237
|
+
DevlogTransport.prototype.buildGetUrl = function (baseUrl, jzb) {
|
|
52238
|
+
var params = {};
|
|
51615
52239
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51616
52240
|
this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51617
52241
|
}
|
|
51618
|
-
|
|
52242
|
+
var jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
51619
52243
|
if (!this.pendo._.isEmpty(jwtOptions)) {
|
|
51620
52244
|
this.pendo._.extend(params, jwtOptions);
|
|
51621
52245
|
}
|
|
51622
52246
|
params.jzb = jzb;
|
|
51623
|
-
|
|
51624
|
-
return
|
|
51625
|
-
}
|
|
51626
|
-
get(url, options) {
|
|
52247
|
+
var queryString = this.pendo._.map(params, function (value, key) { return "".concat(key, "=").concat(value); }).join('&');
|
|
52248
|
+
return "".concat(baseUrl).concat(baseUrl.indexOf('?') !== -1 ? '&' : '?').concat(queryString);
|
|
52249
|
+
};
|
|
52250
|
+
DevlogTransport.prototype.get = function (url, options) {
|
|
51627
52251
|
options.method = 'GET';
|
|
51628
52252
|
if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51629
52253
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
@@ -51631,86 +52255,90 @@ class DevlogTransport {
|
|
|
51631
52255
|
else {
|
|
51632
52256
|
return this.pendo.ajax.get(url);
|
|
51633
52257
|
}
|
|
51634
|
-
}
|
|
51635
|
-
sendRequestWithGet
|
|
51636
|
-
|
|
52258
|
+
};
|
|
52259
|
+
DevlogTransport.prototype.sendRequestWithGet = function (_a) {
|
|
52260
|
+
var url = _a.url, jzb = _a.jzb;
|
|
52261
|
+
var getUrl = this.buildGetUrl(url, jzb);
|
|
51637
52262
|
return this.get(getUrl, {
|
|
51638
52263
|
headers: {
|
|
51639
52264
|
'Content-Type': 'application/octet-stream'
|
|
51640
52265
|
}
|
|
51641
52266
|
});
|
|
51642
|
-
}
|
|
51643
|
-
post(url, options) {
|
|
52267
|
+
};
|
|
52268
|
+
DevlogTransport.prototype.post = function (url, options) {
|
|
51644
52269
|
options.method = 'POST';
|
|
51645
52270
|
if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
51646
52271
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
51647
52272
|
}
|
|
51648
52273
|
else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
|
|
51649
|
-
|
|
52274
|
+
var result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
|
|
51650
52275
|
return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
|
|
51651
52276
|
}
|
|
51652
52277
|
else {
|
|
51653
52278
|
return this.pendo.ajax.post(url, options.body);
|
|
51654
52279
|
}
|
|
51655
|
-
}
|
|
51656
|
-
sendRequestWithPost
|
|
51657
|
-
|
|
51658
|
-
|
|
52280
|
+
};
|
|
52281
|
+
DevlogTransport.prototype.sendRequestWithPost = function (_a, isUnload) {
|
|
52282
|
+
var url = _a.url, jzb = _a.jzb;
|
|
52283
|
+
var jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52284
|
+
var bodyPayload = {
|
|
51659
52285
|
events: jzb,
|
|
51660
52286
|
browser_time: this.pluginAPI.util.getNow()
|
|
51661
52287
|
};
|
|
51662
52288
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
51663
52289
|
this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
51664
52290
|
}
|
|
51665
|
-
|
|
52291
|
+
var body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
|
|
51666
52292
|
return this.post(url, {
|
|
51667
|
-
body,
|
|
52293
|
+
body: body,
|
|
51668
52294
|
headers: {
|
|
51669
52295
|
'Content-Type': 'application/json'
|
|
51670
52296
|
},
|
|
51671
52297
|
keepalive: isUnload
|
|
51672
52298
|
});
|
|
51673
|
-
}
|
|
51674
|
-
sendRequest
|
|
51675
|
-
|
|
52299
|
+
};
|
|
52300
|
+
DevlogTransport.prototype.sendRequest = function (_a, isUnload) {
|
|
52301
|
+
var url = _a.url, jzb = _a.jzb;
|
|
52302
|
+
var compressedLength = jzb.length;
|
|
51676
52303
|
if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
|
|
51677
|
-
return this.sendRequestWithGet({ url, jzb });
|
|
52304
|
+
return this.sendRequestWithGet({ url: url, jzb: jzb });
|
|
51678
52305
|
}
|
|
51679
|
-
return this.sendRequestWithPost({ url, jzb }, isUnload);
|
|
51680
|
-
}
|
|
51681
|
-
|
|
52306
|
+
return this.sendRequestWithPost({ url: url, jzb: jzb }, isUnload);
|
|
52307
|
+
};
|
|
52308
|
+
return DevlogTransport;
|
|
52309
|
+
}());
|
|
51682
52310
|
|
|
51683
52311
|
function ConsoleCapture() {
|
|
51684
|
-
|
|
51685
|
-
|
|
51686
|
-
|
|
51687
|
-
|
|
51688
|
-
|
|
51689
|
-
|
|
51690
|
-
|
|
51691
|
-
|
|
51692
|
-
|
|
51693
|
-
|
|
51694
|
-
|
|
51695
|
-
|
|
52312
|
+
var pluginAPI;
|
|
52313
|
+
var _;
|
|
52314
|
+
var globalPendo;
|
|
52315
|
+
var buffer;
|
|
52316
|
+
var sendQueue;
|
|
52317
|
+
var sendInterval;
|
|
52318
|
+
var transport;
|
|
52319
|
+
var isPtmPaused;
|
|
52320
|
+
var isCapturingConsoleLogs = false;
|
|
52321
|
+
var CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
|
|
52322
|
+
var CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
|
|
52323
|
+
var DEV_LOG_SUB_TYPE = 'console';
|
|
51696
52324
|
// deduplicate logs
|
|
51697
|
-
|
|
52325
|
+
var lastLogKey = '';
|
|
51698
52326
|
return {
|
|
51699
52327
|
name: 'ConsoleCapture',
|
|
51700
|
-
initialize,
|
|
51701
|
-
teardown,
|
|
51702
|
-
addIntercepts,
|
|
51703
|
-
createConsoleEvent,
|
|
51704
|
-
captureStackTrace,
|
|
51705
|
-
send,
|
|
51706
|
-
setCaptureState,
|
|
51707
|
-
recordingStarted,
|
|
51708
|
-
recordingStopped,
|
|
51709
|
-
onAppHidden,
|
|
51710
|
-
onAppUnloaded,
|
|
51711
|
-
onPtmPaused,
|
|
51712
|
-
onPtmUnpaused,
|
|
51713
|
-
securityPolicyViolationFn,
|
|
52328
|
+
initialize: initialize,
|
|
52329
|
+
teardown: teardown,
|
|
52330
|
+
addIntercepts: addIntercepts,
|
|
52331
|
+
createConsoleEvent: createConsoleEvent,
|
|
52332
|
+
captureStackTrace: captureStackTrace,
|
|
52333
|
+
send: send,
|
|
52334
|
+
setCaptureState: setCaptureState,
|
|
52335
|
+
recordingStarted: recordingStarted,
|
|
52336
|
+
recordingStopped: recordingStopped,
|
|
52337
|
+
onAppHidden: onAppHidden,
|
|
52338
|
+
onAppUnloaded: onAppUnloaded,
|
|
52339
|
+
onPtmPaused: onPtmPaused,
|
|
52340
|
+
onPtmUnpaused: onPtmUnpaused,
|
|
52341
|
+
securityPolicyViolationFn: securityPolicyViolationFn,
|
|
51714
52342
|
get isCapturingConsoleLogs() {
|
|
51715
52343
|
return isCapturingConsoleLogs;
|
|
51716
52344
|
},
|
|
@@ -51727,16 +52355,16 @@ function ConsoleCapture() {
|
|
|
51727
52355
|
function initialize(pendo, PluginAPI) {
|
|
51728
52356
|
_ = pendo._;
|
|
51729
52357
|
pluginAPI = PluginAPI;
|
|
51730
|
-
|
|
52358
|
+
var ConfigReader = pluginAPI.ConfigReader;
|
|
51731
52359
|
ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
51732
|
-
|
|
52360
|
+
var captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
|
|
51733
52361
|
if (!captureConsoleEnabled)
|
|
51734
52362
|
return;
|
|
51735
52363
|
globalPendo = pendo;
|
|
51736
52364
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
51737
52365
|
transport = new DevlogTransport(pendo, pluginAPI);
|
|
51738
52366
|
sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
|
|
51739
|
-
sendInterval = setInterval(()
|
|
52367
|
+
sendInterval = setInterval(function () {
|
|
51740
52368
|
if (!sendQueue.failed()) {
|
|
51741
52369
|
send();
|
|
51742
52370
|
}
|
|
@@ -51762,17 +52390,19 @@ function ConsoleCapture() {
|
|
|
51762
52390
|
function onPtmUnpaused() {
|
|
51763
52391
|
isPtmPaused = false;
|
|
51764
52392
|
if (!buffer.isEmpty()) {
|
|
51765
|
-
for (
|
|
51766
|
-
|
|
52393
|
+
for (var _i = 0, _a = buffer.events; _i < _a.length; _i++) {
|
|
52394
|
+
var event_1 = _a[_i];
|
|
52395
|
+
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
51767
52396
|
}
|
|
51768
52397
|
send();
|
|
51769
52398
|
}
|
|
51770
52399
|
}
|
|
51771
|
-
function setCaptureState(
|
|
52400
|
+
function setCaptureState(_a) {
|
|
52401
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
51772
52402
|
if (shouldCapture === isCapturingConsoleLogs)
|
|
51773
52403
|
return;
|
|
51774
52404
|
isCapturingConsoleLogs = shouldCapture;
|
|
51775
|
-
pluginAPI.log.info(
|
|
52405
|
+
pluginAPI.log.info("[ConsoleCapture] Console log capture ".concat(shouldCapture ? 'started' : 'stopped').concat(reason ? ": ".concat(reason) : ''));
|
|
51776
52406
|
}
|
|
51777
52407
|
function recordingStarted() {
|
|
51778
52408
|
setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -51792,12 +52422,12 @@ function ConsoleCapture() {
|
|
|
51792
52422
|
}
|
|
51793
52423
|
function addIntercepts() {
|
|
51794
52424
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
51795
|
-
|
|
52425
|
+
var originalMethod = console[methodName];
|
|
51796
52426
|
if (!originalMethod)
|
|
51797
52427
|
return;
|
|
51798
52428
|
console[methodName] = _.wrap(originalMethod, function (originalFn) {
|
|
51799
52429
|
// slice 1 to omit originalFn
|
|
51800
|
-
|
|
52430
|
+
var args = _.toArray(arguments).slice(1);
|
|
51801
52431
|
originalFn.apply(console, args);
|
|
51802
52432
|
createConsoleEvent(args, methodName);
|
|
51803
52433
|
});
|
|
@@ -51809,10 +52439,10 @@ function ConsoleCapture() {
|
|
|
51809
52439
|
function securityPolicyViolationFn(evt) {
|
|
51810
52440
|
if (!evt || typeof evt !== 'object')
|
|
51811
52441
|
return;
|
|
51812
|
-
|
|
51813
|
-
|
|
51814
|
-
|
|
51815
|
-
|
|
52442
|
+
var blockedURI = evt.blockedURI, violatedDirective = evt.violatedDirective, effectiveDirective = evt.effectiveDirective, disposition = evt.disposition, originalPolicy = evt.originalPolicy;
|
|
52443
|
+
var directive = violatedDirective || effectiveDirective;
|
|
52444
|
+
var isReportOnly = disposition === 'report';
|
|
52445
|
+
var message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
|
|
51816
52446
|
if (isReportOnly) {
|
|
51817
52447
|
createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
|
|
51818
52448
|
}
|
|
@@ -51820,12 +52450,13 @@ function ConsoleCapture() {
|
|
|
51820
52450
|
createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
|
|
51821
52451
|
}
|
|
51822
52452
|
}
|
|
51823
|
-
function createConsoleEvent(args, methodName,
|
|
52453
|
+
function createConsoleEvent(args, methodName, _a) {
|
|
52454
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
|
|
51824
52455
|
if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
|
|
51825
52456
|
return;
|
|
51826
52457
|
// stringify args
|
|
51827
|
-
|
|
51828
|
-
|
|
52458
|
+
var message = _.compact(_.map(args, function (arg) {
|
|
52459
|
+
var stringifiedArg;
|
|
51829
52460
|
try {
|
|
51830
52461
|
stringifiedArg = stringify(arg);
|
|
51831
52462
|
}
|
|
@@ -51837,22 +52468,22 @@ function ConsoleCapture() {
|
|
|
51837
52468
|
if (!message)
|
|
51838
52469
|
return;
|
|
51839
52470
|
// capture stack trace
|
|
51840
|
-
|
|
52471
|
+
var stackTrace = '';
|
|
51841
52472
|
if (!skipStackTrace) {
|
|
51842
|
-
|
|
52473
|
+
var maxStackFrames = methodName === 'error' ? 4 : 1;
|
|
51843
52474
|
stackTrace = captureStackTrace(maxStackFrames);
|
|
51844
52475
|
}
|
|
51845
52476
|
// truncate message and stack trace
|
|
51846
52477
|
message = truncate(message);
|
|
51847
52478
|
stackTrace = truncate(stackTrace);
|
|
51848
52479
|
// de-duplicate log
|
|
51849
|
-
|
|
52480
|
+
var logKey = generateLogKey(methodName, message, stackTrace);
|
|
51850
52481
|
if (isExistingDuplicateLog(logKey)) {
|
|
51851
52482
|
buffer.lastEvent.devLogCount++;
|
|
51852
52483
|
return;
|
|
51853
52484
|
}
|
|
51854
|
-
|
|
51855
|
-
|
|
52485
|
+
var devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52486
|
+
var consoleEvent = __assign(__assign({}, devLogEnvelope), { subType: DEV_LOG_SUB_TYPE, devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: skipScrubPII ? message : scrubPII({ string: message, _: _ }), devLogTrace: stackTrace, devLogCount: 1 });
|
|
51856
52487
|
if (!buffer.hasTokenAvailable())
|
|
51857
52488
|
return consoleEvent;
|
|
51858
52489
|
if (!isPtmPaused) {
|
|
@@ -51864,8 +52495,8 @@ function ConsoleCapture() {
|
|
|
51864
52495
|
}
|
|
51865
52496
|
function captureStackTrace(maxStackFrames) {
|
|
51866
52497
|
try {
|
|
51867
|
-
|
|
51868
|
-
return _.map(stackFrames, frame
|
|
52498
|
+
var stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
|
|
52499
|
+
return _.map(stackFrames, function (frame) { return frame.toString(); }).join('\n');
|
|
51869
52500
|
}
|
|
51870
52501
|
catch (error) {
|
|
51871
52502
|
return '';
|
|
@@ -51877,21 +52508,22 @@ function ConsoleCapture() {
|
|
|
51877
52508
|
function updateLastLog(logKey) {
|
|
51878
52509
|
lastLogKey = logKey;
|
|
51879
52510
|
}
|
|
51880
|
-
function send(
|
|
52511
|
+
function send(_a) {
|
|
52512
|
+
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
51881
52513
|
if (!buffer || buffer.isEmpty())
|
|
51882
52514
|
return;
|
|
51883
52515
|
if (!globalPendo.isSendingEvents()) {
|
|
51884
52516
|
buffer.clear();
|
|
51885
52517
|
return;
|
|
51886
52518
|
}
|
|
51887
|
-
|
|
52519
|
+
var payloads = buffer.pack();
|
|
51888
52520
|
if (!payloads || payloads.length === 0)
|
|
51889
52521
|
return;
|
|
51890
52522
|
if (unload || hidden) {
|
|
51891
52523
|
sendQueue.drain(payloads, unload);
|
|
51892
52524
|
}
|
|
51893
52525
|
else {
|
|
51894
|
-
sendQueue.push(
|
|
52526
|
+
sendQueue.push.apply(sendQueue, payloads);
|
|
51895
52527
|
}
|
|
51896
52528
|
}
|
|
51897
52529
|
function teardown() {
|
|
@@ -51915,7 +52547,7 @@ function ConsoleCapture() {
|
|
|
51915
52547
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
51916
52548
|
if (!console[methodName])
|
|
51917
52549
|
return _.noop;
|
|
51918
|
-
|
|
52550
|
+
var unwrap = console[methodName]._pendoUnwrap;
|
|
51919
52551
|
if (_.isFunction(unwrap)) {
|
|
51920
52552
|
unwrap();
|
|
51921
52553
|
}
|
|
@@ -52090,6 +52722,7 @@ function NetworkCapture() {
|
|
|
52090
52722
|
* Use RegExp for flexible or partial matching.
|
|
52091
52723
|
*
|
|
52092
52724
|
* Example: `['https://example.com', new RegExp('https://test\\.com\\/.*'), /.*\\.domain\\.com/]`
|
|
52725
|
+
*
|
|
52093
52726
|
* @access public
|
|
52094
52727
|
* @category Config/Network Logs
|
|
52095
52728
|
* @name networkLogs.excludeRequestUrls
|
|
@@ -52356,7 +52989,7 @@ var injectStyles = function (pendoContainerId, log) {
|
|
|
52356
52989
|
log("[predict] injecting styles: ".concat(styleId));
|
|
52357
52990
|
createElement('style', {
|
|
52358
52991
|
id: styleId,
|
|
52359
|
-
textContent: "\n #".concat(pendoContainerId, " {\n display: none !important;\n }\n .frame-explanation {\n aspect-ratio: 16/9; overflow: hidden; min-height: 300px;\n width: 100vw; height: 100vh; background: transparent;\n position: fixed; bottom: 0; right: 0; z-index:
|
|
52992
|
+
textContent: "\n #".concat(pendoContainerId, " {\n display: none !important;\n }\n .frame-explanation {\n aspect-ratio: 16/9; overflow: hidden; min-height: 300px;\n width: 100vw; height: 100vh; background: transparent;\n position: fixed; bottom: 0; right: 0; z-index: 1; border: none;\n visibility: hidden; opacity: 0; pointer-events: none;\n transition: opacity 0.1s ease-out, visibility 0s linear 0.1s;\n display: none;\n }\n .frame-explanation.is-visible {\n z-index: 999999;\n visibility: visible; opacity: 1; pointer-events: auto;\n transition: opacity 0.1s ease-out, visibility 0s linear 0s;\n }\n .frame-explanation.is-exists {\n display: block !important;\n }\n .floating-modal-container {\n position: fixed; top: 20px; right: 20px; z-index: 500000;\n visibility: hidden; opacity: 0; pointer-events: none;\n transition: opacity 0.1s ease-out, visibility 0s linear 0.1s;\n border-radius: 8px; box-shadow: 0px 4px 12px 0px rgba(0,0,0,0.15);\n overflow: hidden; width: 384px; height: 176px;\n }\n .floating-modal-container.is-visible {\n visibility: visible; opacity: 1; pointer-events: auto;\n transition: opacity 0.1s ease-out, visibility 0s linear 0s;\n }\n .floating-modal-container.is-dragging { will-change: left, top; }\n .floating-modal-drag-handle {\n position: absolute; left: 50%; transform: translateX(-50%);\n top: 5px; width: calc(100% - 46px); min-width: 166px; height: 17px;\n z-index: 9999; transition: left 0.2s ease, right 0.2s ease;\n display: flex; justify-content: center; align-items: center;\n }\n .floating-modal-drag-handle svg g { fill: #A0A0A0; }\n .floating-modal-drag-handle:hover { cursor: grab; }\n .floating-modal-drag-handle:hover svg g { fill: #1f2937; }\n .floating-modal-drag-handle.is-dragging { cursor: grabbing; }\n .floating-modal-drag-handle.is-collapsed { top: 0px; }\n .frame-floating-modal { width: 100%; height: 100%; background: white; border: none; display: block; }\n ")
|
|
52360
52993
|
}, document.head);
|
|
52361
52994
|
};
|
|
52362
52995
|
var getRecordIdFromUrl = function (recordRegex, log) {
|