@pendo/agent 2.333.0 → 2.334.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 +9 -3
- package/dist/pendo.module.js +1278 -1123
- package/dist/pendo.module.min.js +155 -8
- package/dist/servers.json +16 -7
- package/package.json +1 -1
package/dist/pendo.module.js
CHANGED
|
@@ -3407,6 +3407,7 @@ var ConfigReader = (function () {
|
|
|
3407
3407
|
* @type {boolean}
|
|
3408
3408
|
*/
|
|
3409
3409
|
addOption('disableGuidePseudoStyles', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3410
|
+
addOption('disableImportantStyleAttributes', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
|
|
3410
3411
|
/**
|
|
3411
3412
|
* Content of badge and target element activated guides will be prefetched on load to improve guide display
|
|
3412
3413
|
* time unless set to `true`.
|
|
@@ -4028,8 +4029,8 @@ let SERVER = '';
|
|
|
4028
4029
|
let ASSET_HOST = '';
|
|
4029
4030
|
let ASSET_PATH = '';
|
|
4030
4031
|
let DESIGNER_SERVER = '';
|
|
4031
|
-
let VERSION = '2.
|
|
4032
|
-
let PACKAGE_VERSION = '2.
|
|
4032
|
+
let VERSION = '2.334.0_';
|
|
4033
|
+
let PACKAGE_VERSION = '2.334.0';
|
|
4033
4034
|
let LOADER = 'xhr';
|
|
4034
4035
|
/* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
|
|
4035
4036
|
/**
|
|
@@ -10392,8 +10393,13 @@ var setStyles = function (element, style) {
|
|
|
10392
10393
|
var importantIndex = value.indexOf('!important');
|
|
10393
10394
|
if (importantIndex !== -1) {
|
|
10394
10395
|
try {
|
|
10395
|
-
var propertyValue = trim.call(
|
|
10396
|
-
|
|
10396
|
+
var propertyValue = trim.call(value.substring(0, importantIndex));
|
|
10397
|
+
if (ConfigReader.get('disableImportantStyleAttributes')) {
|
|
10398
|
+
element.style.setProperty(key, propertyValue);
|
|
10399
|
+
}
|
|
10400
|
+
else {
|
|
10401
|
+
element.style.setProperty(key, propertyValue, 'important');
|
|
10402
|
+
}
|
|
10397
10403
|
return;
|
|
10398
10404
|
}
|
|
10399
10405
|
catch (e) { // Fallback for <=IE8
|
|
@@ -11781,12 +11787,12 @@ function isTrustedOrigin(host) {
|
|
|
11781
11787
|
return true;
|
|
11782
11788
|
// Domains that Pendo owns, will be swapped in by build patches
|
|
11783
11789
|
const patterns = [
|
|
11784
|
-
/^https:\/\/(adopt\.)?((us1)\.)?(app|via|adopt|cdn|oem|novus-api|novus)(\.(au|eu|gov|hsbc|jpn))?\.pendo\.io$/,
|
|
11785
|
-
/^https:\/\/([0-9]{8}t[0-9]{4}-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11786
|
-
/^https:\/\/hotfix-(ops|app)-([0-9]+-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11787
|
-
/^https:\/\/(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)-static\.storage\.googleapis\.com$/,
|
|
11790
|
+
/^https:\/\/(adopt\.)?((us1)\.)?(app|via|adopt|cdn|oem|novus-api|novus)(\.(au|eu|gov|hsbc|jpn|tv))?\.pendo\.io$/,
|
|
11791
|
+
/^https:\/\/([0-9]{8}t[0-9]{4}-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-tv|pendo-us1)\.appspot\.com$/,
|
|
11792
|
+
/^https:\/\/hotfix-(ops|app)-([0-9]+-dot-)(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-tv|pendo-us1)\.appspot\.com$/,
|
|
11793
|
+
/^https:\/\/(pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-tv|pendo-us1)-static\.storage\.googleapis\.com$/,
|
|
11788
11794
|
/^https:\/\/([a-zA-Z0-9-]+\.)*pendo-dev\.com$/,
|
|
11789
|
-
/^https:\/\/([a-zA-Z0-9-]+-dot-)?(pendo-apollo|pendo-armada|pendo-atlas|pendo-batman|pendo-calypso|pendo-dap|pendo-dev|pendo-dr-us-east1|pendo-eu-dev|pendo-freeze|pendo-helix|pendo-link|pendo-magic|pendo-mango|pendo-mcfly|pendo-ml|pendo-mobile-fbi|pendo-mobile-guides|pendo-mobile-hummus|pendo-mobile-plat|pendo-perfserf|pendo-voc|pendo-wildlings|pendo-ionchef|pendo-scrum-ops|pendo-security|pendo-test|pendo-uat|pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-us1)\.appspot\.com$/,
|
|
11795
|
+
/^https:\/\/([a-zA-Z0-9-]+-dot-)?(pendo-apollo|pendo-armada|pendo-atlas|pendo-batman|pendo-calypso|pendo-dap|pendo-dev|pendo-dr-us-east1|pendo-eu-dev|pendo-freeze|pendo-helix|pendo-link|pendo-magic|pendo-mango|pendo-mcfly|pendo-ml|pendo-mobile-fbi|pendo-mobile-guides|pendo-mobile-hummus|pendo-mobile-plat|pendo-perfserf|pendo-voc|pendo-wildlings|pendo-ionchef|pendo-scrum-ops|pendo-security|pendo-test|pendo-uat|pendo-au|pendo-eu|pendo-govramp|pendo-hsbc|pendo-io|pendo-jp-prod|pendo-tv|pendo-us1)\.appspot\.com$/,
|
|
11790
11796
|
/^https:\/\/(via|adopt|local)\.pendo\.(local|io):\d{4}$/,
|
|
11791
11797
|
/^https:\/\/(pendo-apollo|pendo-armada|pendo-atlas|pendo-batman|pendo-calypso|pendo-dap|pendo-dev|pendo-dr-us-east1|pendo-eu-dev|pendo-freeze|pendo-helix|pendo-link|pendo-magic|pendo-mango|pendo-mcfly|pendo-ml|pendo-mobile-fbi|pendo-mobile-guides|pendo-mobile-hummus|pendo-mobile-plat|pendo-perfserf|pendo-voc|pendo-wildlings|pendo-ionchef|pendo-scrum-ops|pendo-security|pendo-test|pendo-uat)-static\.storage\.googleapis\.com$/
|
|
11792
11798
|
]; // eslint-disable-line web-sdk-eslint-rules/no-gulp-env-references
|
|
@@ -17949,6 +17955,7 @@ function buildNodeFromJSON(json, step, guides) {
|
|
|
17949
17955
|
var id = json.props && json.props.id;
|
|
17950
17956
|
// This builds the 4pc backdrop to allow block clicking for any guide without changing how the backdrop is saved
|
|
17951
17957
|
if (id === 'pendo-backdrop') {
|
|
17958
|
+
step.hasBackdrop = true;
|
|
17952
17959
|
return buildBackdrop(step);
|
|
17953
17960
|
}
|
|
17954
17961
|
_.each(json.props, function (propValue, propKey) {
|
|
@@ -23217,7 +23224,7 @@ function autofocusRuntimeScript(step, guide, pendo) {
|
|
|
23217
23224
|
if (pendo._.get(step, 'attributes.isAutoFocus')) {
|
|
23218
23225
|
BuildingBlockGuides.autofocusStep(step, guideContainer);
|
|
23219
23226
|
BuildingBlockGuides.trapFocusStep(step, guideContainer);
|
|
23220
|
-
step.hiddenElements = BuildingBlockGuides.
|
|
23227
|
+
step.hiddenElements = BuildingBlockGuides.addAriaHiddenOutsideGuide(step.guideElement[0]);
|
|
23221
23228
|
}
|
|
23222
23229
|
if (isGuideRCType(guide)) {
|
|
23223
23230
|
BuildingBlockGuides.attachRCFocusHandlers();
|
|
@@ -23234,6 +23241,20 @@ var autofocusStep = {
|
|
|
23234
23241
|
script: autofocusRuntimeScript
|
|
23235
23242
|
};
|
|
23236
23243
|
|
|
23244
|
+
function backdropInertRuntimeScript(step, guide, pendo) {
|
|
23245
|
+
if (pendo.designer || !step.guideElement)
|
|
23246
|
+
return;
|
|
23247
|
+
if (step.hasBackdrop) {
|
|
23248
|
+
const BuildingBlockGuides = pendo.BuildingBlocks.BuildingBlockGuides;
|
|
23249
|
+
const excludeElements = getTargetAreaElementsForBlockOut(step);
|
|
23250
|
+
const inertElements = BuildingBlockGuides.addInertOutsideGuide(step.guideElement[0], [], excludeElements);
|
|
23251
|
+
step.hiddenElements = (step.hiddenElements || []).concat(inertElements);
|
|
23252
|
+
}
|
|
23253
|
+
}
|
|
23254
|
+
var backdropInertStep = {
|
|
23255
|
+
script: backdropInertRuntimeScript
|
|
23256
|
+
};
|
|
23257
|
+
|
|
23237
23258
|
function isTooltip({ _ }, step) {
|
|
23238
23259
|
const tooltip = 'tooltip';
|
|
23239
23260
|
return _.get(step, 'attributes.calculatedType') === tooltip ||
|
|
@@ -23391,6 +23412,7 @@ function registerPostrenderScripts(runtime) {
|
|
|
23391
23412
|
advanceOnElement,
|
|
23392
23413
|
announcementMarkSeen,
|
|
23393
23414
|
autofocusStep,
|
|
23415
|
+
backdropInertStep,
|
|
23394
23416
|
repositionOnScroll,
|
|
23395
23417
|
setFocusToActivationElement$1,
|
|
23396
23418
|
videoLoadingAttribute
|
|
@@ -24647,7 +24669,8 @@ var loadGuides = function (apiKey, visitorId, page, callback) {
|
|
|
24647
24669
|
visitorId,
|
|
24648
24670
|
accountId: get_account_id(),
|
|
24649
24671
|
url: page,
|
|
24650
|
-
oldVisitorId: get_old_visitor_id()
|
|
24672
|
+
oldVisitorId: get_old_visitor_id(),
|
|
24673
|
+
timezoneOffset: (new Date()).getTimezoneOffset()
|
|
24651
24674
|
};
|
|
24652
24675
|
const reqId = _.uniqueId();
|
|
24653
24676
|
loadGuides.reqId = reqId;
|
|
@@ -29559,7 +29582,8 @@ var BuildingBlockGuides = (function () {
|
|
|
29559
29582
|
autofocusStep,
|
|
29560
29583
|
trapFocusStep,
|
|
29561
29584
|
attachRCFocusHandlers,
|
|
29562
|
-
|
|
29585
|
+
addAriaHiddenOutsideGuide,
|
|
29586
|
+
addInertOutsideGuide,
|
|
29563
29587
|
renderResourceCenterModule: BuildingBlockResourceCenter.renderResourceCenterModule,
|
|
29564
29588
|
buildNodeFromJSON,
|
|
29565
29589
|
attachImgLoadHandlers,
|
|
@@ -29627,6 +29651,7 @@ var BuildingBlockGuides = (function () {
|
|
|
29627
29651
|
}
|
|
29628
29652
|
var isAnnouncementModule = _.get(guide, 'attributes.resourceCenter.moduleId') === 'AnnouncementsModule';
|
|
29629
29653
|
step.hasEscapeListener = false;
|
|
29654
|
+
step.hasBackdrop = false;
|
|
29630
29655
|
step.containerId = containerJSON && containerJSON.props && containerJSON.props.id;
|
|
29631
29656
|
step.element = getElementForGuideStep(step, options.document);
|
|
29632
29657
|
var modifiableJSON = unwrapFirefoxObject(json);
|
|
@@ -29929,7 +29954,7 @@ var BuildingBlockGuides = (function () {
|
|
|
29929
29954
|
function trapFocusStep(step, guideContainer) {
|
|
29930
29955
|
var guideContainerElement = guideContainer.find('#pendo-guide-container');
|
|
29931
29956
|
var targetElement = _.get(step, 'attributes.blockOutUI.enabled') && getTargetElementForStep(step);
|
|
29932
|
-
trapFocus(guideContainerElement, targetElement);
|
|
29957
|
+
trapFocus(guideContainerElement, targetElement, step);
|
|
29933
29958
|
}
|
|
29934
29959
|
function getSelectedPollElementForFocus(focusableChildren, bumperElement) {
|
|
29935
29960
|
let elementToFocus;
|
|
@@ -29942,41 +29967,71 @@ var BuildingBlockGuides = (function () {
|
|
|
29942
29967
|
}
|
|
29943
29968
|
return elementToFocus || bumperElement;
|
|
29944
29969
|
}
|
|
29970
|
+
function isTabbable(element) {
|
|
29971
|
+
if (!isElementVisible(element))
|
|
29972
|
+
return false;
|
|
29973
|
+
if (element.tagName === 'IFRAME')
|
|
29974
|
+
return true;
|
|
29975
|
+
if (element.tabIndex >= 0 && !element.disabled)
|
|
29976
|
+
return true;
|
|
29977
|
+
var editable = element.getAttribute && element.getAttribute('contenteditable');
|
|
29978
|
+
return editable != null && editable !== 'false';
|
|
29979
|
+
}
|
|
29945
29980
|
function collectTargetFocusables(targetElement) {
|
|
29946
29981
|
if (!targetElement)
|
|
29947
29982
|
return [];
|
|
29948
|
-
var focusables =
|
|
29949
|
-
|
|
29950
|
-
|
|
29951
|
-
|
|
29983
|
+
var focusables = [];
|
|
29984
|
+
var collect = function (node) {
|
|
29985
|
+
if (node.nodeType === 1 && isTabbable(node)) {
|
|
29986
|
+
focusables.push(node);
|
|
29987
|
+
}
|
|
29988
|
+
if (node.shadowRoot) {
|
|
29989
|
+
_.each(node.shadowRoot.children, collect);
|
|
29990
|
+
}
|
|
29991
|
+
_.each(node.children, collect);
|
|
29992
|
+
};
|
|
29993
|
+
collect(targetElement);
|
|
29952
29994
|
return focusables;
|
|
29953
29995
|
}
|
|
29954
|
-
function
|
|
29955
|
-
var
|
|
29956
|
-
|
|
29957
|
-
|
|
29958
|
-
|
|
29959
|
-
|
|
29960
|
-
return bumper;
|
|
29996
|
+
function getDeepActiveElement() {
|
|
29997
|
+
var active = document.activeElement;
|
|
29998
|
+
while (active && active.shadowRoot && active.shadowRoot.activeElement) {
|
|
29999
|
+
active = active.shadowRoot.activeElement;
|
|
30000
|
+
}
|
|
30001
|
+
return active;
|
|
29961
30002
|
}
|
|
29962
|
-
function
|
|
29963
|
-
if (!
|
|
29964
|
-
return
|
|
29965
|
-
var
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
29969
|
-
|
|
30003
|
+
function isWithinComposedTree(root, element) {
|
|
30004
|
+
if (!root || !element)
|
|
30005
|
+
return false;
|
|
30006
|
+
var node = element;
|
|
30007
|
+
while (node) {
|
|
30008
|
+
if (node.nodeType === 1 && root.contains(node))
|
|
30009
|
+
return true;
|
|
30010
|
+
var rootNode = dom.getRootNode(node);
|
|
30011
|
+
node = rootNode && rootNode.host;
|
|
30012
|
+
}
|
|
30013
|
+
return false;
|
|
29970
30014
|
}
|
|
29971
|
-
function
|
|
29972
|
-
|
|
29973
|
-
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
|
|
30015
|
+
function isWithinAdditionalBlockOutAreas(element, step) {
|
|
30016
|
+
var selectors = _.get(step, 'attributes.blockOutUI.additionalElements');
|
|
30017
|
+
if (!_.isString(selectors) || !selectors.length)
|
|
30018
|
+
return false;
|
|
30019
|
+
return _.some(selectors.replace(/\s/g, '').split(','), function (selector) {
|
|
30020
|
+
if (!selector)
|
|
30021
|
+
return false;
|
|
30022
|
+
var areas;
|
|
30023
|
+
try {
|
|
30024
|
+
areas = dom(selector);
|
|
30025
|
+
}
|
|
30026
|
+
catch (e) {
|
|
30027
|
+
return false;
|
|
30028
|
+
}
|
|
30029
|
+
return _.some(areas, function (area) {
|
|
30030
|
+
return isWithinComposedTree(area, element);
|
|
30031
|
+
});
|
|
29977
30032
|
});
|
|
29978
30033
|
}
|
|
29979
|
-
function trapFocus(guideContainerElement, targetElement) {
|
|
30034
|
+
function trapFocus(guideContainerElement, targetElement, step) {
|
|
29980
30035
|
var containerNode = guideContainerElement[0];
|
|
29981
30036
|
if (!containerNode) {
|
|
29982
30037
|
return;
|
|
@@ -30007,18 +30062,16 @@ var BuildingBlockGuides = (function () {
|
|
|
30007
30062
|
var bumpers = insertTrapFocusBumpers(guideContainerElement);
|
|
30008
30063
|
var startFocusBumper = bumpers[0];
|
|
30009
30064
|
var endFocusBumper = bumpers[1];
|
|
30010
|
-
var
|
|
30011
|
-
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
|
|
30015
|
-
|
|
30016
|
-
|
|
30017
|
-
|
|
30018
|
-
|
|
30019
|
-
|
|
30020
|
-
var wrapForward = firstTargetFocusable || firstFocusableEl;
|
|
30021
|
-
var wrapBackward = lastTargetFocusable || lastFocusableEl;
|
|
30065
|
+
var isOutsideTrap = function (element) {
|
|
30066
|
+
var guideRoot = step && step.guideElement && step.guideElement[0];
|
|
30067
|
+
return !!element &&
|
|
30068
|
+
element !== document.body &&
|
|
30069
|
+
element !== document.documentElement &&
|
|
30070
|
+
!containerNode.contains(element) &&
|
|
30071
|
+
!(guideRoot && isWithinComposedTree(guideRoot, element)) &&
|
|
30072
|
+
!isWithinComposedTree(targetElement, element) &&
|
|
30073
|
+
!isWithinAdditionalBlockOutAreas(element, step);
|
|
30074
|
+
};
|
|
30022
30075
|
var trapFocusCallback = function (e) {
|
|
30023
30076
|
if (!isTabEvent(e)) {
|
|
30024
30077
|
return;
|
|
@@ -30031,34 +30084,31 @@ var BuildingBlockGuides = (function () {
|
|
|
30031
30084
|
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
|
|
30032
30085
|
const startBumperActive = activeElement === startFocusBumper;
|
|
30033
30086
|
const endBumperActive = activeElement === endFocusBumper;
|
|
30034
|
-
const
|
|
30035
|
-
const
|
|
30036
|
-
const
|
|
30037
|
-
const onLastTargetFocusable = isKeydown &&
|
|
30038
|
-
|
|
30087
|
+
const deepActive = getDeepActiveElement();
|
|
30088
|
+
const targetFocusables = collectTargetFocusables(targetElement);
|
|
30089
|
+
const activeTargetIndex = deepActive ? targetFocusables.indexOf(deepActive) : -1;
|
|
30090
|
+
const onLastTargetFocusable = isKeydown && activeTargetIndex !== -1 &&
|
|
30091
|
+
activeTargetIndex === targetFocusables.length - 1;
|
|
30092
|
+
const onFirstTargetFocusable = isKeydown && activeTargetIndex === 0;
|
|
30039
30093
|
let elementToFocus;
|
|
30040
30094
|
if (isShiftPressed) {
|
|
30041
30095
|
if (onFirstTargetFocusable)
|
|
30042
30096
|
elementToFocus = lastFocusableEl;
|
|
30043
|
-
else if (
|
|
30044
|
-
elementToFocus = lastFocusableEl;
|
|
30045
|
-
|
|
30046
|
-
elementToFocus = lastTargetFocusable;
|
|
30047
|
-
else if (startBumperActive || containerActive || bodyActive)
|
|
30048
|
-
elementToFocus = wrapBackward;
|
|
30097
|
+
else if (startBumperActive || containerActive || bodyActive) {
|
|
30098
|
+
elementToFocus = targetFocusables[targetFocusables.length - 1] || lastFocusableEl;
|
|
30099
|
+
}
|
|
30049
30100
|
}
|
|
30050
30101
|
else {
|
|
30051
30102
|
if (onLastTargetFocusable)
|
|
30052
30103
|
elementToFocus = firstFocusableEl;
|
|
30053
|
-
else if (afterTargetBumperActive)
|
|
30054
|
-
elementToFocus = firstFocusableEl;
|
|
30055
|
-
else if (beforeTargetBumperActive)
|
|
30056
|
-
elementToFocus = firstTargetFocusable;
|
|
30057
30104
|
else if (endBumperActive)
|
|
30058
|
-
elementToFocus =
|
|
30105
|
+
elementToFocus = targetFocusables[0] || firstFocusableEl;
|
|
30059
30106
|
else if (containerActive || bodyActive)
|
|
30060
30107
|
elementToFocus = firstFocusableEl;
|
|
30061
30108
|
}
|
|
30109
|
+
if (!elementToFocus && targetFocusables.length && isOutsideTrap(deepActive)) {
|
|
30110
|
+
elementToFocus = isShiftPressed ? lastFocusableEl : firstFocusableEl;
|
|
30111
|
+
}
|
|
30062
30112
|
if (elementToFocus) {
|
|
30063
30113
|
const resolved = getSelectedPollElementForFocus(focusableChildren, elementToFocus);
|
|
30064
30114
|
resolved.focus();
|
|
@@ -30068,13 +30118,23 @@ var BuildingBlockGuides = (function () {
|
|
|
30068
30118
|
e.preventDefault();
|
|
30069
30119
|
}
|
|
30070
30120
|
};
|
|
30071
|
-
|
|
30121
|
+
var iframeExitCallback = function (e) {
|
|
30122
|
+
var fromTargetIframe = e.relatedTarget && e.relatedTarget.tagName === 'IFRAME' &&
|
|
30123
|
+
isWithinComposedTree(targetElement, e.relatedTarget);
|
|
30124
|
+
if (!fromTargetIframe || !isOutsideTrap(e.target))
|
|
30125
|
+
return;
|
|
30126
|
+
var exitedForward = !!(e.relatedTarget.compareDocumentPosition(e.target) & Node.DOCUMENT_POSITION_FOLLOWING);
|
|
30127
|
+
(exitedForward ? firstFocusableEl : lastFocusableEl).focus();
|
|
30128
|
+
};
|
|
30072
30129
|
attachEvent(document, 'keyup', trapFocusCallback);
|
|
30073
30130
|
attachEvent(document, 'keydown', trapFocusCallback);
|
|
30131
|
+
if (targetElement) {
|
|
30132
|
+
attachEvent(document, 'focusin', iframeExitCallback);
|
|
30133
|
+
}
|
|
30074
30134
|
Events.one('unmounted', () => {
|
|
30075
30135
|
detachEvent(document, 'keyup', trapFocusCallback);
|
|
30076
30136
|
detachEvent(document, 'keydown', trapFocusCallback);
|
|
30077
|
-
|
|
30137
|
+
detachEvent(document, 'focusin', iframeExitCallback);
|
|
30078
30138
|
});
|
|
30079
30139
|
}
|
|
30080
30140
|
// bumpers are divs with a tabindex to allow them to be focused, but which should immediately
|
|
@@ -30145,22 +30205,42 @@ var BuildingBlockGuides = (function () {
|
|
|
30145
30205
|
domElem.append(endFocusBumper);
|
|
30146
30206
|
return [startFocusBumper, endFocusBumper];
|
|
30147
30207
|
}
|
|
30148
|
-
function
|
|
30208
|
+
function addAriaHiddenOutsideGuide(elem, hidden = []) {
|
|
30209
|
+
if (!elem || elem === getBody())
|
|
30210
|
+
return hidden;
|
|
30211
|
+
const siblings = getSiblings(elem);
|
|
30212
|
+
_.each(siblings, (s) => {
|
|
30213
|
+
if (hidden.indexOf(s) === -1 && s.getAttribute('aria-hidden') !== 'true') {
|
|
30214
|
+
const tagName = s.tagName.toLowerCase();
|
|
30215
|
+
if (tagName !== 'script' && tagName !== 'style') {
|
|
30216
|
+
s.setAttribute('aria-hidden', 'true');
|
|
30217
|
+
hidden.push(s);
|
|
30218
|
+
}
|
|
30219
|
+
}
|
|
30220
|
+
});
|
|
30221
|
+
if (elem.parentNode) {
|
|
30222
|
+
addAriaHiddenOutsideGuide(elem.parentNode, hidden);
|
|
30223
|
+
}
|
|
30224
|
+
return hidden;
|
|
30225
|
+
}
|
|
30226
|
+
function addInertOutsideGuide(elem, hidden = [], excludeElements = []) {
|
|
30149
30227
|
if (!elem || elem === getBody())
|
|
30150
30228
|
return hidden;
|
|
30151
30229
|
const supportsInert = isNaN(msie);
|
|
30152
|
-
|
|
30230
|
+
if (!supportsInert)
|
|
30231
|
+
return hidden;
|
|
30153
30232
|
const siblings = getSiblings(elem);
|
|
30154
30233
|
_.each(siblings, (s) => {
|
|
30155
30234
|
const tagName = s.tagName.toLowerCase();
|
|
30156
|
-
const alreadyDisabled = s.getAttribute(
|
|
30157
|
-
|
|
30158
|
-
|
|
30235
|
+
const alreadyDisabled = s.getAttribute('inert') === 'true';
|
|
30236
|
+
const isExcluded = _.some(excludeElements, (excluded) => excluded && (s === excluded || s.contains(excluded)));
|
|
30237
|
+
if (hidden.indexOf(s) === -1 && !alreadyDisabled && !isExcluded && tagName !== 'script' && tagName !== 'style') {
|
|
30238
|
+
s.setAttribute('inert', 'true');
|
|
30159
30239
|
hidden.push(s);
|
|
30160
30240
|
}
|
|
30161
30241
|
});
|
|
30162
30242
|
if (elem.parentNode) {
|
|
30163
|
-
|
|
30243
|
+
addInertOutsideGuide(elem.parentNode, hidden, excludeElements);
|
|
30164
30244
|
}
|
|
30165
30245
|
return hidden;
|
|
30166
30246
|
}
|
|
@@ -36488,6 +36568,7 @@ var DOMActivation = (function () {
|
|
|
36488
36568
|
}
|
|
36489
36569
|
})();
|
|
36490
36570
|
|
|
36571
|
+
const REPOSITION_PHASE = 'embeddedGuidesReposition';
|
|
36491
36572
|
const EmbeddedGuides = (function () {
|
|
36492
36573
|
let pluginApi;
|
|
36493
36574
|
let globalPendo;
|
|
@@ -36507,15 +36588,42 @@ const EmbeddedGuides = (function () {
|
|
|
36507
36588
|
GuideStepFactory.behaviors.push(EmbeddedGuideStep);
|
|
36508
36589
|
pluginApi.Events.on('deliverablesLoaded', initializeEmbeddedGuides);
|
|
36509
36590
|
pluginApi.Events.on('eventCaptured', eventCaptured);
|
|
36591
|
+
// APP-161235: embedded guides render as auto-display guides in the guide
|
|
36592
|
+
// loop, and their dynamic-height content can shift the document position
|
|
36593
|
+
// of elements that *other* guides' tooltips are anchored to (e.g. a badge
|
|
36594
|
+
// below the embed). This phase is appended after the built-in loop phases
|
|
36595
|
+
// (so it runs once the embed has rendered this pass) and re-anchors those
|
|
36596
|
+
// tooltips to the settled layout, instead of leaving them detached until a
|
|
36597
|
+
// later pass corrects them (visibly "floating" on a heavy loop).
|
|
36598
|
+
pluginApi.GuideLoop.addUpdatePhase(repositionGuidesAfterEmbedLayout, REPOSITION_PHASE);
|
|
36510
36599
|
}
|
|
36511
36600
|
function teardown() {
|
|
36512
36601
|
pluginApi.Events.off('deliverablesLoaded', initializeEmbeddedGuides);
|
|
36513
36602
|
pluginApi.Events.off('eventCaptured', eventCaptured);
|
|
36603
|
+
pluginApi.GuideLoop.removeUpdatePhase(REPOSITION_PHASE);
|
|
36514
36604
|
const index = GuideStepFactory.behaviors.indexOf(EmbeddedGuideStep);
|
|
36515
36605
|
if (index !== -1) {
|
|
36516
36606
|
GuideStepFactory.behaviors.splice(index, 1);
|
|
36517
36607
|
}
|
|
36518
36608
|
}
|
|
36609
|
+
function isShown(guide) {
|
|
36610
|
+
return !!(guide && _.isFunction(guide.isShown) && guide.isShown());
|
|
36611
|
+
}
|
|
36612
|
+
function repositionGuidesAfterEmbedLayout() {
|
|
36613
|
+
// Only run when one of our embedded guides is actually shown — the only
|
|
36614
|
+
// condition under which the embed's layout can displace other tooltips.
|
|
36615
|
+
if (!_.some(embeddedGuides, isShown))
|
|
36616
|
+
return;
|
|
36617
|
+
_.each(globalPendo.guides, function (guide) {
|
|
36618
|
+
if (isEmbedded(guide) || !isShown(guide))
|
|
36619
|
+
return;
|
|
36620
|
+
_.each(guide.steps, function (step) {
|
|
36621
|
+
if (_.isFunction(step.isShown) && step.isShown() && _.isFunction(step.checkPlacement)) {
|
|
36622
|
+
step.checkPlacement();
|
|
36623
|
+
}
|
|
36624
|
+
});
|
|
36625
|
+
});
|
|
36626
|
+
}
|
|
36519
36627
|
function eventCaptured(event) {
|
|
36520
36628
|
const capturedEvent = _.get(event, 'data.0');
|
|
36521
36629
|
if (!capturedEvent || capturedEvent.type !== 'guideSeen')
|
|
@@ -41211,7 +41319,8 @@ const channels = [
|
|
|
41211
41319
|
}]
|
|
41212
41320
|
];
|
|
41213
41321
|
const WEB_ANALYTICS_STORAGE_KEY = 'utm';
|
|
41214
|
-
const
|
|
41322
|
+
const ENABLE_FULL_REFERRER_CONFIG_KEY = 'enableFullUtmReferrer';
|
|
41323
|
+
const DISABLE_REFERRER_CONFIG_KEY = 'disableUtmReferrer';
|
|
41215
41324
|
class WebAnalytics {
|
|
41216
41325
|
constructor() {
|
|
41217
41326
|
this.name = 'WebAnalytics';
|
|
@@ -41220,7 +41329,11 @@ class WebAnalytics {
|
|
|
41220
41329
|
this.pendo = pendo;
|
|
41221
41330
|
this.api = PluginAPI;
|
|
41222
41331
|
const { ConfigReader } = PluginAPI;
|
|
41223
|
-
ConfigReader.addOption(
|
|
41332
|
+
ConfigReader.addOption(ENABLE_FULL_REFERRER_CONFIG_KEY, [
|
|
41333
|
+
ConfigReader.sources.SNIPPET_SRC,
|
|
41334
|
+
ConfigReader.sources.PENDO_CONFIG_SRC
|
|
41335
|
+
], false);
|
|
41336
|
+
ConfigReader.addOption(DISABLE_REFERRER_CONFIG_KEY, [
|
|
41224
41337
|
ConfigReader.sources.SNIPPET_SRC,
|
|
41225
41338
|
ConfigReader.sources.PENDO_CONFIG_SRC
|
|
41226
41339
|
], false);
|
|
@@ -41268,14 +41381,16 @@ class WebAnalytics {
|
|
|
41268
41381
|
content
|
|
41269
41382
|
};
|
|
41270
41383
|
utm.channel = this.calculateUtmChannel({ referrerValue, utm, gclid, fbclid });
|
|
41271
|
-
if (
|
|
41272
|
-
|
|
41273
|
-
|
|
41274
|
-
|
|
41275
|
-
|
|
41276
|
-
|
|
41277
|
-
|
|
41278
|
-
|
|
41384
|
+
if (!this.api.ConfigReader.get(DISABLE_REFERRER_CONFIG_KEY)) {
|
|
41385
|
+
if (referrer && this.api.ConfigReader.get(ENABLE_FULL_REFERRER_CONFIG_KEY)) {
|
|
41386
|
+
utm.referrer = referrer;
|
|
41387
|
+
}
|
|
41388
|
+
else if (referrerValue === 'self') {
|
|
41389
|
+
utm.referrer = currentHost;
|
|
41390
|
+
}
|
|
41391
|
+
else if (referrerValue !== 'direct') {
|
|
41392
|
+
utm.referrer = referrerValue;
|
|
41393
|
+
}
|
|
41279
41394
|
}
|
|
41280
41395
|
return utm;
|
|
41281
41396
|
}
|
|
@@ -41613,19 +41728,17 @@ function getDefaultExportFromCjs (x) {
|
|
|
41613
41728
|
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
|
|
41614
41729
|
}
|
|
41615
41730
|
|
|
41616
|
-
|
|
41617
|
-
|
|
41618
|
-
|
|
41619
|
-
|
|
41620
|
-
|
|
41621
|
-
function lookupGuideButtons(domJson, buttons) {
|
|
41622
|
-
if (buttons === void 0) { buttons = []; }
|
|
41731
|
+
const substitutionRegex = '\\{(?:\\s?)([^.\\s]?visitor|account|parentAccount)\\.([^|\\s/]*)(?:\\s?\\|\\s?([^}]+|[\\/s]+))?(?:\\s?\\/\\s?){1}\\}';
|
|
41732
|
+
const skipStepString = '{skipStep:* *(auto|\\d+)\\/}';
|
|
41733
|
+
const goToMiddleString = '(?!0)(\\d+)';
|
|
41734
|
+
const goToString = `({goto-${goToMiddleString}\\/})`;
|
|
41735
|
+
const containerSelector = '[id^="pendo-guide-container"]';
|
|
41736
|
+
function lookupGuideButtons(domJson, buttons = []) {
|
|
41623
41737
|
if (domJson.type === 'button' && domJson.actions) {
|
|
41624
41738
|
buttons.push(domJson);
|
|
41625
41739
|
}
|
|
41626
41740
|
if (domJson.children) {
|
|
41627
|
-
for (
|
|
41628
|
-
var child = _a[_i];
|
|
41741
|
+
for (const child of domJson.children) {
|
|
41629
41742
|
lookupGuideButtons(child, buttons);
|
|
41630
41743
|
}
|
|
41631
41744
|
}
|
|
@@ -41652,16 +41765,15 @@ function removeMarkdownSyntax(element, textToReplace, replacementText, pendo) {
|
|
|
41652
41765
|
}
|
|
41653
41766
|
}
|
|
41654
41767
|
var guideMarkdownUtil = {
|
|
41655
|
-
substitutionRegex
|
|
41656
|
-
skipStepString
|
|
41657
|
-
goToString
|
|
41658
|
-
containerSelector
|
|
41659
|
-
lookupGuideButtons
|
|
41660
|
-
removeMarkdownSyntax
|
|
41768
|
+
substitutionRegex,
|
|
41769
|
+
skipStepString,
|
|
41770
|
+
goToString,
|
|
41771
|
+
containerSelector,
|
|
41772
|
+
lookupGuideButtons,
|
|
41773
|
+
removeMarkdownSyntax
|
|
41661
41774
|
};
|
|
41662
41775
|
|
|
41663
|
-
function getZoneSafeMethod(_, method, target) {
|
|
41664
|
-
if (target === void 0) { target = window; }
|
|
41776
|
+
function getZoneSafeMethod(_, method, target = window) {
|
|
41665
41777
|
var zoneSymbol = '__symbol__';
|
|
41666
41778
|
/* global Zone */
|
|
41667
41779
|
if (typeof Zone !== 'undefined' && _.isFunction(Zone[zoneSymbol])) {
|
|
@@ -41674,20 +41786,20 @@ function getZoneSafeMethod(_, method, target) {
|
|
|
41674
41786
|
}
|
|
41675
41787
|
|
|
41676
41788
|
// Does not support submit and go to
|
|
41677
|
-
|
|
41678
|
-
|
|
41789
|
+
const goToRegex = new RegExp(guideMarkdownUtil.goToString);
|
|
41790
|
+
const PollBranching = {
|
|
41679
41791
|
name: 'PollBranching',
|
|
41680
|
-
script
|
|
41681
|
-
|
|
41682
|
-
|
|
41792
|
+
script(step, guide, pendo) {
|
|
41793
|
+
let isAdvanceIntercepted = false;
|
|
41794
|
+
const branchingQuestions = initialBranchingSetup(step, pendo);
|
|
41683
41795
|
if (branchingQuestions) {
|
|
41684
41796
|
// If there are too many branching questions saved, exit and run the guide normally.
|
|
41685
41797
|
if (pendo._.size(branchingQuestions) > 1)
|
|
41686
41798
|
return;
|
|
41687
|
-
this.on('beforeAdvance',
|
|
41688
|
-
|
|
41689
|
-
|
|
41690
|
-
|
|
41799
|
+
this.on('beforeAdvance', (evt) => {
|
|
41800
|
+
const noResponseSelected = step.guideElement.find('[branching] .pendo-radio:checked').length === 0;
|
|
41801
|
+
const responseLabel = step.guideElement.find('[branching] .pendo-radio:checked + label')[0];
|
|
41802
|
+
let noGotoLabel;
|
|
41691
41803
|
if (responseLabel) {
|
|
41692
41804
|
noGotoLabel = pendo._.isNull(responseLabel.getAttribute('goToStep'));
|
|
41693
41805
|
}
|
|
@@ -41698,58 +41810,58 @@ var PollBranching = {
|
|
|
41698
41810
|
});
|
|
41699
41811
|
}
|
|
41700
41812
|
},
|
|
41701
|
-
test
|
|
41813
|
+
test(step, guide, pendo) {
|
|
41702
41814
|
var _a;
|
|
41703
|
-
|
|
41815
|
+
let branchingQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41704
41816
|
return !pendo._.isUndefined(branchingQuestions) && pendo._.size(branchingQuestions);
|
|
41705
41817
|
},
|
|
41706
|
-
designerListener
|
|
41707
|
-
|
|
41708
|
-
|
|
41818
|
+
designerListener(pendo) {
|
|
41819
|
+
const target = pendo.dom.getBody();
|
|
41820
|
+
const config = {
|
|
41709
41821
|
attributeFilter: ['data-layout'],
|
|
41710
41822
|
attributes: true,
|
|
41711
41823
|
childList: true,
|
|
41712
41824
|
characterData: true,
|
|
41713
41825
|
subtree: true
|
|
41714
41826
|
};
|
|
41715
|
-
|
|
41716
|
-
|
|
41827
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
41828
|
+
const observer = new MutationObserver(applyBranchingIndicators);
|
|
41717
41829
|
observer.observe(target, config);
|
|
41718
41830
|
function applyBranchingIndicators(mutations) {
|
|
41719
41831
|
pendo._.each(mutations, function (mutation) {
|
|
41720
41832
|
var _a;
|
|
41721
|
-
|
|
41833
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelector);
|
|
41722
41834
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
41723
41835
|
if (mutation.addedNodes[0].querySelector('._pendo-multi-choice-poll-select-border')) {
|
|
41724
41836
|
if (pendo._.size(pendo.dom('._pendo-multi-choice-poll-question:contains("{branching/}")'))) {
|
|
41725
41837
|
pendo
|
|
41726
41838
|
.dom('._pendo-multi-choice-poll-question:contains("{branching/}")')
|
|
41727
|
-
.each(
|
|
41728
|
-
pendo._.each(pendo.dom(
|
|
41839
|
+
.each((question, index) => {
|
|
41840
|
+
pendo._.each(pendo.dom(`#${question.id} *`), (element) => {
|
|
41729
41841
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41730
41842
|
});
|
|
41731
41843
|
pendo
|
|
41732
|
-
.dom(
|
|
41844
|
+
.dom(`#${question.id} p`)
|
|
41733
41845
|
.css({ display: 'inline-block !important' })
|
|
41734
41846
|
.append(branchingIcon('#999', '20px'))
|
|
41735
41847
|
.attr({ title: 'Custom Branching Added' });
|
|
41736
|
-
|
|
41737
|
-
if (pendo.dom(
|
|
41848
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41849
|
+
if (pendo.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]) {
|
|
41738
41850
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
41739
41851
|
pendo
|
|
41740
|
-
.dom(
|
|
41852
|
+
.dom(`._pendo-multi-choice-poll-question[data-pendo-poll-id=${dataPendoPollId}]`)[0]
|
|
41741
41853
|
.textContent.trim();
|
|
41742
41854
|
}
|
|
41743
|
-
|
|
41855
|
+
let pollLabels = pendo.dom(`label[for*=${dataPendoPollId}]`);
|
|
41744
41856
|
if (pendo._.size(pollLabels)) {
|
|
41745
|
-
pendo._.forEach(pollLabels,
|
|
41857
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41746
41858
|
if (goToRegex.test(label.textContent)) {
|
|
41747
|
-
|
|
41859
|
+
let labelTitle = goToRegex.exec(label.textContent)[2];
|
|
41748
41860
|
guideMarkdownUtil.removeMarkdownSyntax(label, goToRegex, '', pendo);
|
|
41749
41861
|
pendo
|
|
41750
41862
|
.dom(label)
|
|
41751
41863
|
.append(branchingIcon('#999', '14px'))
|
|
41752
|
-
.attr({ title:
|
|
41864
|
+
.attr({ title: `Branching to step ${labelTitle}` });
|
|
41753
41865
|
}
|
|
41754
41866
|
});
|
|
41755
41867
|
}
|
|
@@ -41757,9 +41869,9 @@ var PollBranching = {
|
|
|
41757
41869
|
pendo
|
|
41758
41870
|
.dom(question)
|
|
41759
41871
|
.append(branchingErrorHTML(question.dataset.pendoPollId));
|
|
41760
|
-
pendo.dom(
|
|
41872
|
+
pendo.dom(`#${question.id} #pendo-ps-branching-svg`).remove();
|
|
41761
41873
|
pendo
|
|
41762
|
-
.dom(
|
|
41874
|
+
.dom(`#${question.id} p`)
|
|
41763
41875
|
.css({ display: 'inline-block !important' })
|
|
41764
41876
|
.append(branchingIcon('red', '20px'))
|
|
41765
41877
|
.attr({ title: 'Unsupported Branching configuration' });
|
|
@@ -41771,31 +41883,49 @@ var PollBranching = {
|
|
|
41771
41883
|
});
|
|
41772
41884
|
}
|
|
41773
41885
|
function branchingErrorHTML(dataPendoPollId) {
|
|
41774
|
-
return
|
|
41886
|
+
return `<div style="text-align:lrft; font-size: 14px; color: red;
|
|
41887
|
+
font-style: italic; margin-top: 0px;" class="branching-wrapper"
|
|
41888
|
+
name="${dataPendoPollId}">
|
|
41889
|
+
* Branching Error: Multiple branching polls not supported</div>`;
|
|
41775
41890
|
}
|
|
41776
41891
|
function branchingIcon(color, size) {
|
|
41777
|
-
return
|
|
41892
|
+
return `<svg id="pendo-ps-branching-svg" viewBox="0 0 24 24" fill="none"
|
|
41893
|
+
style="margin-left: 5px;
|
|
41894
|
+
height:${size}; width:${size}; display:inline; vertical-align:middle;" xmlns="http://www.w3.org/2000/svg">
|
|
41895
|
+
<g stroke-width="0"></g>
|
|
41896
|
+
<g stroke-linecap="round" stroke-linejoin="round"></g>
|
|
41897
|
+
<g> <circle cx="4" cy="7" r="2" stroke="${color}"
|
|
41898
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41899
|
+
<circle cx="20" cy="7" r="2" stroke="${color}"
|
|
41900
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41901
|
+
<circle cx="20" cy="17" r="2" stroke="${color}" stroke-width="2"
|
|
41902
|
+
stroke-linecap="round" stroke-linejoin="round"></circle>
|
|
41903
|
+
<path d="M18 7H6" stroke="${color}" stroke-width="2"
|
|
41904
|
+
stroke-linecap="round" stroke-linejoin="round"></path>
|
|
41905
|
+
<path d="M7 7V7C8.65685 7 10 8.34315 10 10V15C10 16.1046 10.8954 17 12 17H18"
|
|
41906
|
+
stroke="${color}" stroke-width="2" stroke-linecap="round"
|
|
41907
|
+
stroke-linejoin="round"></path> </g></svg>`;
|
|
41778
41908
|
}
|
|
41779
41909
|
}
|
|
41780
41910
|
};
|
|
41781
41911
|
function initialBranchingSetup(step, pendo) {
|
|
41782
|
-
|
|
41783
|
-
pendo._.forEach(questions,
|
|
41784
|
-
|
|
41785
|
-
pendo._.each(step.guideElement.find(
|
|
41912
|
+
const questions = step.guideElement.find('._pendo-multi-choice-poll-question:contains("{branching/}")');
|
|
41913
|
+
pendo._.forEach(questions, (question) => {
|
|
41914
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
41915
|
+
pendo._.each(step.guideElement.find(`#${question.id} *`), (element) => {
|
|
41786
41916
|
guideMarkdownUtil.removeMarkdownSyntax(element, '{branching/}', '', pendo);
|
|
41787
41917
|
});
|
|
41788
|
-
|
|
41789
|
-
pendo._.forEach(pollLabels,
|
|
41918
|
+
let pollLabels = step.guideElement.find(`label[for*=${dataPendoPollId}]`);
|
|
41919
|
+
pendo._.forEach(pollLabels, (label) => {
|
|
41790
41920
|
if (pendo._.isNull(goToRegex.exec(label.textContent))) {
|
|
41791
41921
|
return;
|
|
41792
41922
|
}
|
|
41793
|
-
|
|
41794
|
-
|
|
41923
|
+
let gotoSubstring = goToRegex.exec(label.textContent)[1];
|
|
41924
|
+
let gotoIndex = goToRegex.exec(label.textContent)[2];
|
|
41795
41925
|
label.setAttribute('goToStep', gotoIndex);
|
|
41796
41926
|
guideMarkdownUtil.removeMarkdownSyntax(label, gotoSubstring, '', pendo);
|
|
41797
41927
|
});
|
|
41798
|
-
|
|
41928
|
+
let pollChoiceContainer = step.guideElement.find(`[data-pendo-poll-id=${dataPendoPollId}]._pendo-multi-choice-poll-select-border`);
|
|
41799
41929
|
if (pollChoiceContainer && pollChoiceContainer.length) {
|
|
41800
41930
|
pollChoiceContainer[0].setAttribute('branching', '');
|
|
41801
41931
|
}
|
|
@@ -41804,39 +41934,38 @@ function initialBranchingSetup(step, pendo) {
|
|
|
41804
41934
|
}
|
|
41805
41935
|
function branchingGoToStep(event, step, guide, pendo) {
|
|
41806
41936
|
var _a;
|
|
41807
|
-
|
|
41808
|
-
|
|
41809
|
-
|
|
41810
|
-
|
|
41937
|
+
let checkedPollInputId = (_a = step.guideElement.find('[branching] input.pendo-radio[data-pendo-poll-id]:checked')[0]) === null || _a === void 0 ? void 0 : _a.id;
|
|
41938
|
+
let checkedPollLabel = step.guideElement.find(`label[for="${checkedPollInputId}"]`)[0];
|
|
41939
|
+
let checkedPollLabelStepIndex = checkedPollLabel === null || checkedPollLabel === void 0 ? void 0 : checkedPollLabel.getAttribute('goToStep');
|
|
41940
|
+
let pollStepIndex = checkedPollLabelStepIndex - 1;
|
|
41811
41941
|
if (pollStepIndex < 0)
|
|
41812
41942
|
return;
|
|
41813
|
-
|
|
41943
|
+
const destinationObject = {
|
|
41814
41944
|
destinationStepId: guide.steps[pollStepIndex].id,
|
|
41815
|
-
step
|
|
41945
|
+
step
|
|
41816
41946
|
};
|
|
41817
41947
|
pendo.goToStep(destinationObject);
|
|
41818
41948
|
event.cancel = true;
|
|
41819
41949
|
}
|
|
41820
41950
|
|
|
41821
|
-
|
|
41822
|
-
function encodeMetadataForUrl(value, urlBeforePlaceholder) {
|
|
41823
|
-
|
|
41824
|
-
|
|
41825
|
-
var inUrlComponent = urlBeforePlaceholder.indexOf('?') !== -1 || urlBeforePlaceholder.indexOf('#') !== -1;
|
|
41951
|
+
const DANGEROUS_URL_SCHEME = /^\s*(javascript|data|vbscript):/i;
|
|
41952
|
+
function encodeMetadataForUrl(value, urlBeforePlaceholder = '') {
|
|
41953
|
+
const str = value === undefined || value === null ? '' : String(value);
|
|
41954
|
+
const inUrlComponent = urlBeforePlaceholder.indexOf('?') !== -1 || urlBeforePlaceholder.indexOf('#') !== -1;
|
|
41826
41955
|
if (inUrlComponent) {
|
|
41827
41956
|
return window.encodeURIComponent(str);
|
|
41828
41957
|
}
|
|
41829
|
-
|
|
41958
|
+
const schemeAlreadySet = urlBeforePlaceholder.indexOf(':') !== -1;
|
|
41830
41959
|
if (!schemeAlreadySet && DANGEROUS_URL_SCHEME.test(str)) {
|
|
41831
41960
|
return '';
|
|
41832
41961
|
}
|
|
41833
41962
|
return window.encodeURI(str);
|
|
41834
41963
|
}
|
|
41835
41964
|
|
|
41836
|
-
|
|
41965
|
+
const MetadataSubstitution = {
|
|
41837
41966
|
name: 'MetadataSubstitution',
|
|
41838
|
-
script
|
|
41839
|
-
|
|
41967
|
+
script(step, guide, pendo) {
|
|
41968
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41840
41969
|
if (step.domJson) {
|
|
41841
41970
|
findSubstitutableUrlsInJson(step.domJson, placeholderData, pendo);
|
|
41842
41971
|
}
|
|
@@ -41844,22 +41973,22 @@ var MetadataSubstitution = {
|
|
|
41844
41973
|
pendo._.each(placeholderData, function (placeholder) {
|
|
41845
41974
|
processPlaceholder(placeholder, pendo);
|
|
41846
41975
|
});
|
|
41847
|
-
|
|
41848
|
-
|
|
41849
|
-
updateGuideContainer(containerId,
|
|
41976
|
+
const containerId = `pendo-g-${step.id}`;
|
|
41977
|
+
const context = step.guideElement;
|
|
41978
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41850
41979
|
}
|
|
41851
41980
|
},
|
|
41852
|
-
designerListener
|
|
41853
|
-
|
|
41981
|
+
designerListener(pendo) {
|
|
41982
|
+
const target = pendo.dom.getBody();
|
|
41854
41983
|
if (pendo.designerv2) {
|
|
41855
41984
|
pendo.designerv2.runMetadataSubstitutionForDesignerPreview = function runMetadataSubstitutionForDesignerPreview() {
|
|
41856
41985
|
var _a;
|
|
41857
41986
|
if (!document.querySelector(guideMarkdownUtil.containerSelector))
|
|
41858
41987
|
return;
|
|
41859
|
-
|
|
41988
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41860
41989
|
if (!step)
|
|
41861
41990
|
return;
|
|
41862
|
-
|
|
41991
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
41863
41992
|
if (step.buildingBlocks) {
|
|
41864
41993
|
findSubstitutableUrlsInJson(step.buildingBlocks, placeholderData, pendo);
|
|
41865
41994
|
}
|
|
@@ -41869,32 +41998,32 @@ var MetadataSubstitution = {
|
|
|
41869
41998
|
return;
|
|
41870
41999
|
processPlaceholder(placeholder, pendo);
|
|
41871
42000
|
});
|
|
41872
|
-
|
|
41873
|
-
|
|
41874
|
-
updateGuideContainer(containerId,
|
|
42001
|
+
const containerId = `pendo-g-${step.id}`;
|
|
42002
|
+
const context = step.guideElement;
|
|
42003
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41875
42004
|
}
|
|
41876
42005
|
};
|
|
41877
42006
|
}
|
|
41878
|
-
|
|
42007
|
+
const config = {
|
|
41879
42008
|
attributeFilter: ['data-layout'],
|
|
41880
42009
|
attributes: true,
|
|
41881
42010
|
childList: true,
|
|
41882
42011
|
characterData: true,
|
|
41883
42012
|
subtree: true
|
|
41884
42013
|
};
|
|
41885
|
-
|
|
41886
|
-
|
|
42014
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42015
|
+
const observer = new MutationObserver(applySubstitutionIndicators);
|
|
41887
42016
|
observer.observe(target, config);
|
|
41888
42017
|
function applySubstitutionIndicators(mutations) {
|
|
41889
42018
|
pendo._.each(mutations, function (mutation) {
|
|
41890
42019
|
var _a;
|
|
41891
42020
|
if (mutation.addedNodes.length) {
|
|
41892
42021
|
if (document.querySelector(guideMarkdownUtil.containerSelector)) {
|
|
41893
|
-
|
|
41894
|
-
|
|
42022
|
+
const placeholderData = findSubstitutableElements(pendo);
|
|
42023
|
+
const step = (_a = pendo.designerv2.currentlyPreviewedGuide) === null || _a === void 0 ? void 0 : _a.steps[0];
|
|
41895
42024
|
if (!step)
|
|
41896
42025
|
return;
|
|
41897
|
-
|
|
42026
|
+
const pendoBlocks = step.buildingBlocks;
|
|
41898
42027
|
if (!pendo._.isUndefined(pendoBlocks)) {
|
|
41899
42028
|
findSubstitutableUrlsInJson(pendoBlocks, placeholderData, pendo);
|
|
41900
42029
|
}
|
|
@@ -41904,9 +42033,9 @@ var MetadataSubstitution = {
|
|
|
41904
42033
|
return;
|
|
41905
42034
|
processPlaceholder(placeholder, pendo);
|
|
41906
42035
|
});
|
|
41907
|
-
|
|
41908
|
-
|
|
41909
|
-
updateGuideContainer(containerId,
|
|
42036
|
+
const containerId = `pendo-g-${step.id}`;
|
|
42037
|
+
const context = step.guideElement;
|
|
42038
|
+
updateGuideContainer(containerId, context, pendo);
|
|
41910
42039
|
}
|
|
41911
42040
|
}
|
|
41912
42041
|
}
|
|
@@ -41915,18 +42044,18 @@ var MetadataSubstitution = {
|
|
|
41915
42044
|
}
|
|
41916
42045
|
};
|
|
41917
42046
|
function processPlaceholder(placeholder, pendo) {
|
|
41918
|
-
|
|
41919
|
-
|
|
41920
|
-
|
|
42047
|
+
let match;
|
|
42048
|
+
const { data, target } = placeholder;
|
|
42049
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41921
42050
|
while ((match = matchPlaceholder(placeholder, subRegex))) {
|
|
41922
|
-
|
|
41923
|
-
|
|
42051
|
+
const usedArrayPath = Array.isArray(match) && match.length >= 2;
|
|
42052
|
+
const currentStr = target === 'textContent'
|
|
41924
42053
|
? data[target]
|
|
41925
42054
|
: decodeURI((data.getAttribute && (target === 'href' || target === 'value') ? (data.getAttribute(target) || '') : data[target]));
|
|
41926
|
-
|
|
42055
|
+
const matched = usedArrayPath ? match : subRegex.exec(currentStr);
|
|
41927
42056
|
if (!matched)
|
|
41928
42057
|
continue;
|
|
41929
|
-
|
|
42058
|
+
const mdValue = getSubstituteValue(matched, pendo);
|
|
41930
42059
|
substituteMetadataByTarget(data, target, mdValue, matched);
|
|
41931
42060
|
}
|
|
41932
42061
|
}
|
|
@@ -41935,50 +42064,50 @@ function matchPlaceholder(placeholder, regex) {
|
|
|
41935
42064
|
return placeholder.data[placeholder.target].match(regex);
|
|
41936
42065
|
}
|
|
41937
42066
|
else {
|
|
41938
|
-
|
|
42067
|
+
const raw = placeholder.data.getAttribute && (placeholder.target === 'href' || placeholder.target === 'value')
|
|
41939
42068
|
? (placeholder.data.getAttribute(placeholder.target) || '')
|
|
41940
42069
|
: placeholder.data[placeholder.target];
|
|
41941
42070
|
return decodeURI(raw).match(regex);
|
|
41942
42071
|
}
|
|
41943
42072
|
}
|
|
41944
42073
|
function getMetadataValueCaseInsensitive(metadata, type, property) {
|
|
41945
|
-
|
|
42074
|
+
const kind = metadata && metadata[type];
|
|
41946
42075
|
if (!kind || typeof kind !== 'object')
|
|
41947
42076
|
return undefined;
|
|
41948
|
-
|
|
42077
|
+
const direct = Object.prototype.hasOwnProperty.call(kind, property) ? kind[property] : undefined;
|
|
41949
42078
|
if (direct !== undefined) {
|
|
41950
42079
|
return direct;
|
|
41951
42080
|
}
|
|
41952
|
-
|
|
41953
|
-
|
|
41954
|
-
|
|
42081
|
+
const propLower = property.toLowerCase();
|
|
42082
|
+
const key = Object.keys(kind).find(k => k.toLowerCase() === propLower);
|
|
42083
|
+
const value = key !== undefined ? kind[key] : undefined;
|
|
41955
42084
|
return value;
|
|
41956
42085
|
}
|
|
41957
42086
|
function getSubstituteValue(match, pendo) {
|
|
41958
42087
|
if (pendo._.isUndefined(match[1]) || pendo._.isUndefined(match[2])) {
|
|
41959
42088
|
return;
|
|
41960
42089
|
}
|
|
41961
|
-
|
|
41962
|
-
|
|
41963
|
-
|
|
42090
|
+
let type = match[1];
|
|
42091
|
+
let property = match[2];
|
|
42092
|
+
let defaultValue = match[3];
|
|
41964
42093
|
if (pendo._.isUndefined(type) || pendo._.isUndefined(property)) {
|
|
41965
42094
|
return;
|
|
41966
42095
|
}
|
|
41967
|
-
|
|
41968
|
-
|
|
42096
|
+
const metadata = pendo.getSerializedMetadata();
|
|
42097
|
+
let mdValue = getMetadataValueCaseInsensitive(metadata, type, property);
|
|
41969
42098
|
if (mdValue === undefined || mdValue === null)
|
|
41970
42099
|
mdValue = defaultValue || '';
|
|
41971
42100
|
return mdValue;
|
|
41972
42101
|
}
|
|
41973
42102
|
function substituteMetadataByTarget(data, target, mdValue, matched) {
|
|
41974
|
-
|
|
41975
|
-
|
|
42103
|
+
const isElement = data && typeof data.getAttribute === 'function';
|
|
42104
|
+
const current = (target === 'href' || target === 'value') && isElement
|
|
41976
42105
|
? (data.getAttribute(target) || '')
|
|
41977
42106
|
: data[target];
|
|
41978
42107
|
if (target === 'href' || target === 'value') {
|
|
41979
|
-
|
|
41980
|
-
|
|
41981
|
-
|
|
42108
|
+
const decodedUrl = decodeURI(current);
|
|
42109
|
+
const urlBeforePlaceholder = decodedUrl.slice(0, decodedUrl.indexOf(matched[0]));
|
|
42110
|
+
const safeValue = encodeMetadataForUrl(mdValue, urlBeforePlaceholder);
|
|
41982
42111
|
data[target] = decodedUrl.replace(matched[0], safeValue);
|
|
41983
42112
|
}
|
|
41984
42113
|
else {
|
|
@@ -41992,9 +42121,8 @@ function updateGuideContainer(containerId, context, pendo) {
|
|
|
41992
42121
|
pendo.flexElement(pendo.dom(guideMarkdownUtil.containerSelector));
|
|
41993
42122
|
pendo.BuildingBlocks.BuildingBlockGuides.recalculateGuideHeight(containerId, context);
|
|
41994
42123
|
}
|
|
41995
|
-
function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
41996
|
-
|
|
41997
|
-
var subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
42124
|
+
function findSubstitutableUrlsInJson(originalData, placeholderData = [], pendo) {
|
|
42125
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
41998
42126
|
if ((originalData.name === 'url' || originalData.name === 'href') && originalData.value) {
|
|
41999
42127
|
if (subRegex.test(originalData.value)) {
|
|
42000
42128
|
placeholderData.push({
|
|
@@ -42004,37 +42132,37 @@ function findSubstitutableUrlsInJson(originalData, placeholderData, pendo) {
|
|
|
42004
42132
|
}
|
|
42005
42133
|
}
|
|
42006
42134
|
if (originalData.properties && originalData.id === 'href_link_block') {
|
|
42007
|
-
pendo._.each(originalData.properties,
|
|
42135
|
+
pendo._.each(originalData.properties, (prop) => {
|
|
42008
42136
|
findSubstitutableUrlsInJson(prop, placeholderData, pendo);
|
|
42009
42137
|
});
|
|
42010
42138
|
}
|
|
42011
42139
|
if (originalData.views) {
|
|
42012
|
-
pendo._.each(originalData.views,
|
|
42140
|
+
pendo._.each(originalData.views, (view) => {
|
|
42013
42141
|
findSubstitutableUrlsInJson(view, placeholderData, pendo);
|
|
42014
42142
|
});
|
|
42015
42143
|
}
|
|
42016
42144
|
if (originalData.parameters) {
|
|
42017
|
-
pendo._.each(originalData.parameters,
|
|
42145
|
+
pendo._.each(originalData.parameters, (param) => {
|
|
42018
42146
|
findSubstitutableUrlsInJson(param, placeholderData, pendo);
|
|
42019
42147
|
});
|
|
42020
42148
|
}
|
|
42021
42149
|
if (originalData.actions) {
|
|
42022
|
-
pendo._.each(originalData.actions,
|
|
42150
|
+
pendo._.each(originalData.actions, (action) => {
|
|
42023
42151
|
findSubstitutableUrlsInJson(action, placeholderData, pendo);
|
|
42024
42152
|
});
|
|
42025
42153
|
}
|
|
42026
42154
|
if (originalData.children) {
|
|
42027
|
-
pendo._.each(originalData.children,
|
|
42155
|
+
pendo._.each(originalData.children, (child) => {
|
|
42028
42156
|
findSubstitutableUrlsInJson(child, placeholderData, pendo);
|
|
42029
42157
|
});
|
|
42030
42158
|
}
|
|
42031
42159
|
return placeholderData;
|
|
42032
42160
|
}
|
|
42033
42161
|
function findSubstitutableElements(pendo) {
|
|
42034
|
-
|
|
42162
|
+
let elements = pendo.dom(`${guideMarkdownUtil.containerSelector} *:not(.pendo-inline-ui)`);
|
|
42035
42163
|
return pendo._.chain(elements)
|
|
42036
42164
|
.filter(function (placeholder) {
|
|
42037
|
-
|
|
42165
|
+
const subRegex = new RegExp(guideMarkdownUtil.substitutionRegex);
|
|
42038
42166
|
if (placeholder.localName === 'a') {
|
|
42039
42167
|
return subRegex.test(decodeURI(placeholder.href)) || subRegex.test(placeholder.textContent);
|
|
42040
42168
|
}
|
|
@@ -42090,25 +42218,51 @@ function findSubstitutableElements(pendo) {
|
|
|
42090
42218
|
.value();
|
|
42091
42219
|
}
|
|
42092
42220
|
function substitutionIcon(color, size) {
|
|
42093
|
-
return (
|
|
42094
|
-
|
|
42095
|
-
|
|
42096
|
-
|
|
42097
|
-
|
|
42098
|
-
|
|
42221
|
+
return (`<div title="Metadata Substitution added">
|
|
42222
|
+
<svg id="pendo-ps-substitution-icon" viewBox="0 0 24 24"
|
|
42223
|
+
preserveAspectRatio="xMidYMid meet"
|
|
42224
|
+
height=${size} width=${size} title="Metadata Substitution"
|
|
42225
|
+
style="bottom:5px; right:10px; position: absolute;"
|
|
42226
|
+
fill="none" xmlns="http://www.w3.org/2000/svg" stroke="${color}"
|
|
42227
|
+
transform="matrix(1, 0, 0, 1, 0, 0)rotate(0)">
|
|
42228
|
+
<g stroke-width="0"></g>
|
|
42229
|
+
<g stroke-linecap="round" stroke-linejoin="round"
|
|
42230
|
+
stroke="${color}" stroke-width="0.528"></g>
|
|
42231
|
+
<g><path fill-rule="evenodd" clip-rule="evenodd"
|
|
42232
|
+
d="M5 5.5C4.17157 5.5 3.5 6.17157 3.5 7V10C3.5 10.8284
|
|
42233
|
+
4.17157 11.5 5 11.5H8C8.82843 11.5 9.5 10.8284 9.5
|
|
42234
|
+
10V9H17V11C17 11.2761 17.2239 11.5 17.5 11.5C17.7761
|
|
42235
|
+
11.5 18 11.2761 18 11V8.5C18 8.22386 17.7761 8 17.5
|
|
42236
|
+
8H9.5V7C9.5 6.17157 8.82843 5.5 8 5.5H5ZM8.5 7C8.5
|
|
42237
|
+
6.72386 8.27614 6.5 8 6.5H5C4.72386 6.5 4.5 6.72386
|
|
42238
|
+
4.5 7V10C4.5 10.2761 4.72386 10.5 5 10.5H8C8.27614
|
|
42239
|
+
10.5 8.5 10.2761 8.5 10V7Z" fill="${color}"></path>
|
|
42240
|
+
<path fill-rule="evenodd" clip-rule="evenodd"
|
|
42241
|
+
d="M7 13C7 12.7239 6.77614 12.5 6.5 12.5C6.22386 12.5
|
|
42242
|
+
6 12.7239 6 13V15.5C6 15.7761 6.22386 16 6.5
|
|
42243
|
+
16H14.5V17C14.5 17.8284 15.1716 18.5 16 18.5H19C19.8284
|
|
42244
|
+
18.5 20.5 17.8284 20.5 17V14C20.5 13.1716 19.8284 12.5
|
|
42245
|
+
19 12.5H16C15.1716 12.5 14.5 13.1716 14.5
|
|
42246
|
+
14V15H7V13ZM15.5 17C15.5 17.2761 15.7239 17.5 16
|
|
42247
|
+
17.5H19C19.2761 17.5 19.5 17.2761 19.5 17V14C19.5
|
|
42248
|
+
13.7239 19.2761 13.5 19 13.5H16C15.7239 13.5 15.5
|
|
42249
|
+
13.7239 15.5 14V17Z" fill="${color}"></path> </g></svg></div>`);
|
|
42250
|
+
}
|
|
42251
|
+
|
|
42252
|
+
const requiredElement = '<span class="_pendo-required-indicator" style="color:red; font-style:italic;" title="Question is required"> *</span>';
|
|
42253
|
+
const requiredSyntax = '{required/}';
|
|
42254
|
+
const RequiredQuestions = {
|
|
42099
42255
|
name: 'RequiredQuestions',
|
|
42100
|
-
script
|
|
42256
|
+
script(step, guide, pendo) {
|
|
42101
42257
|
var _a;
|
|
42102
|
-
|
|
42103
|
-
|
|
42104
|
-
|
|
42105
|
-
});
|
|
42106
|
-
var requiredQuestions = processRequiredQuestions();
|
|
42258
|
+
let requiredPollIds = [];
|
|
42259
|
+
let submitButtons = (_a = guideMarkdownUtil.lookupGuideButtons(step.domJson)) === null || _a === void 0 ? void 0 : _a.filter(button => button.actions.find(action => action.action === 'submitPoll' || action.action === 'submitPollAndGoToStep'));
|
|
42260
|
+
const requiredQuestions = processRequiredQuestions();
|
|
42107
42261
|
if (requiredQuestions) {
|
|
42108
|
-
pendo._.forEach(requiredQuestions,
|
|
42262
|
+
pendo._.forEach(requiredQuestions, (question) => {
|
|
42109
42263
|
if (question.classList.contains('_pendo-open-text-poll-question')) {
|
|
42110
|
-
|
|
42111
|
-
step.attachEvent(step.guideElement.find(
|
|
42264
|
+
let pollId = question.dataset.pendoPollId;
|
|
42265
|
+
step.attachEvent(step.guideElement.find(`[data-pendo-poll-id=${pollId}]._pendo-open-text-poll-input`)[0], 'input', function () {
|
|
42112
42266
|
evaluateRequiredQuestions(requiredQuestions);
|
|
42113
42267
|
});
|
|
42114
42268
|
}
|
|
@@ -42120,13 +42274,11 @@ var RequiredQuestions = {
|
|
|
42120
42274
|
});
|
|
42121
42275
|
}
|
|
42122
42276
|
function getEligibleQuestions() {
|
|
42123
|
-
|
|
42124
|
-
|
|
42125
|
-
|
|
42126
|
-
|
|
42127
|
-
|
|
42128
|
-
var allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
42129
|
-
return pendo._.reduce(allQuestions, function (eligibleQuestions, question) {
|
|
42277
|
+
const pollQuestions = pendo._.toArray(step.guideElement.find(`[class*=-poll-question]:contains(${requiredSyntax})`));
|
|
42278
|
+
const surveyMatches = pendo._.toArray(step.guideElement.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`));
|
|
42279
|
+
const surveyQuestions = pendo._.filter(surveyMatches, (candidate) => !pendo._.some(surveyMatches, (other) => other !== candidate && candidate.contains(other)));
|
|
42280
|
+
const allQuestions = pendo._.uniq(pollQuestions.concat(surveyQuestions));
|
|
42281
|
+
return pendo._.reduce(allQuestions, (eligibleQuestions, question) => {
|
|
42130
42282
|
if (question.classList.contains('_pendo-yes-no-poll-question'))
|
|
42131
42283
|
return eligibleQuestions;
|
|
42132
42284
|
eligibleQuestions.push(question);
|
|
@@ -42134,24 +42286,22 @@ var RequiredQuestions = {
|
|
|
42134
42286
|
}, []);
|
|
42135
42287
|
}
|
|
42136
42288
|
function ownsRequiredText(element) {
|
|
42137
|
-
return pendo._.some(element.childNodes,
|
|
42138
|
-
return node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1;
|
|
42139
|
-
});
|
|
42289
|
+
return pendo._.some(element.childNodes, (node) => node.nodeType === 3 && node.nodeValue && node.nodeValue.indexOf(requiredSyntax) !== -1);
|
|
42140
42290
|
}
|
|
42141
42291
|
function processRequiredQuestions() {
|
|
42142
|
-
|
|
42292
|
+
let questions = getEligibleQuestions();
|
|
42143
42293
|
if (questions) {
|
|
42144
|
-
pendo._.forEach(questions,
|
|
42145
|
-
|
|
42294
|
+
pendo._.forEach(questions, question => {
|
|
42295
|
+
let dataPendoPollId = question.getAttribute('data-pendo-poll-id');
|
|
42146
42296
|
requiredPollIds.push(dataPendoPollId);
|
|
42147
|
-
|
|
42148
|
-
|
|
42149
|
-
pendo._.each(candidates,
|
|
42297
|
+
const candidates = step.guideElement.find(`#${question.id} *, #${question.id}`);
|
|
42298
|
+
const textHost = pendo._.find(candidates, ownsRequiredText) || question;
|
|
42299
|
+
pendo._.each(candidates, (element) => {
|
|
42150
42300
|
guideMarkdownUtil.removeMarkdownSyntax(element, requiredSyntax, '', pendo);
|
|
42151
42301
|
});
|
|
42152
|
-
|
|
42302
|
+
const textHostEl = pendo.dom(textHost);
|
|
42153
42303
|
if (textHostEl.find('._pendo-required-indicator').length === 0) {
|
|
42154
|
-
|
|
42304
|
+
const questionParagraph = textHostEl.find('p');
|
|
42155
42305
|
if (questionParagraph && questionParagraph.length) {
|
|
42156
42306
|
pendo.dom(questionParagraph[0]).append(requiredElement);
|
|
42157
42307
|
}
|
|
@@ -42162,7 +42312,15 @@ var RequiredQuestions = {
|
|
|
42162
42312
|
});
|
|
42163
42313
|
}
|
|
42164
42314
|
if (pendo._.size(requiredPollIds)) {
|
|
42165
|
-
|
|
42315
|
+
const disabledButtonStyles = `<style type=text/css
|
|
42316
|
+
id=_pendo-guide-required-disabled>
|
|
42317
|
+
._pendo-button:disabled, ._pendo-buttons[disabled] {
|
|
42318
|
+
border: 1px solid #999999 !important;
|
|
42319
|
+
background-color: #cccccc !important;
|
|
42320
|
+
color: #666666 !important;
|
|
42321
|
+
pointer-events: none !important;
|
|
42322
|
+
}
|
|
42323
|
+
</style>`;
|
|
42166
42324
|
if (pendo.dom('#_pendo-guide-required-disabled').length === 0) {
|
|
42167
42325
|
pendo.dom('head').append(disabledButtonStyles);
|
|
42168
42326
|
}
|
|
@@ -42173,11 +42331,15 @@ var RequiredQuestions = {
|
|
|
42173
42331
|
function evaluateRequiredQuestions(questions) {
|
|
42174
42332
|
if (questions.length === 0)
|
|
42175
42333
|
return;
|
|
42176
|
-
|
|
42177
|
-
|
|
42178
|
-
responses = responses.concat(pendo._.map(questions,
|
|
42179
|
-
|
|
42180
|
-
|
|
42334
|
+
let allRequiredComplete = true;
|
|
42335
|
+
let responses = [];
|
|
42336
|
+
responses = responses.concat(pendo._.map(questions, (question) => {
|
|
42337
|
+
let pollId = question.getAttribute('data-pendo-poll-id');
|
|
42338
|
+
let input = step.guideElement.find(`
|
|
42339
|
+
[data-pendo-poll-id=${pollId}] textarea,
|
|
42340
|
+
[data-pendo-poll-id=${pollId}] input:text,
|
|
42341
|
+
[data-pendo-poll-id=${pollId}] select,
|
|
42342
|
+
[data-pendo-poll-id=${pollId}] input:radio:checked`);
|
|
42181
42343
|
if (input && input.length && input[0].value) {
|
|
42182
42344
|
return input[0].value;
|
|
42183
42345
|
}
|
|
@@ -42194,50 +42356,50 @@ var RequiredQuestions = {
|
|
|
42194
42356
|
}
|
|
42195
42357
|
function disableEligibleButtons(buttons) {
|
|
42196
42358
|
pendo._.each(buttons, function (button) {
|
|
42197
|
-
if (step.guideElement.find(
|
|
42198
|
-
step.guideElement.find(
|
|
42199
|
-
step.guideElement.find(
|
|
42359
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
42360
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = true;
|
|
42361
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = 'Please complete all required questions.';
|
|
42200
42362
|
}
|
|
42201
42363
|
});
|
|
42202
42364
|
}
|
|
42203
42365
|
function enableEligibleButtons(buttons) {
|
|
42204
42366
|
pendo._.each(buttons, function (button) {
|
|
42205
|
-
if (step.guideElement.find(
|
|
42206
|
-
step.guideElement.find(
|
|
42207
|
-
step.guideElement.find(
|
|
42367
|
+
if (step.guideElement.find(`#${button.props.id}`)[0]) {
|
|
42368
|
+
step.guideElement.find(`#${button.props.id}`)[0].disabled = false;
|
|
42369
|
+
step.guideElement.find(`#${button.props.id}`)[0].parentElement.title = '';
|
|
42208
42370
|
}
|
|
42209
42371
|
});
|
|
42210
42372
|
}
|
|
42211
42373
|
},
|
|
42212
|
-
test
|
|
42374
|
+
test(step, guide, pendo) {
|
|
42213
42375
|
var _a, _b;
|
|
42214
|
-
|
|
42215
|
-
|
|
42376
|
+
const pollQuestions = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(`[class*=-poll-question]:contains(${requiredSyntax})`);
|
|
42377
|
+
const surveyQuestions = (_b = step.guideElement) === null || _b === void 0 ? void 0 : _b.find(`[data-pendo-poll-id]:contains(${requiredSyntax})`);
|
|
42216
42378
|
return (!pendo._.isUndefined(pollQuestions) && pendo._.size(pollQuestions)) ||
|
|
42217
42379
|
(!pendo._.isUndefined(surveyQuestions) && pendo._.size(surveyQuestions));
|
|
42218
42380
|
},
|
|
42219
|
-
designerListener
|
|
42220
|
-
|
|
42221
|
-
|
|
42222
|
-
|
|
42381
|
+
designerListener(pendo) {
|
|
42382
|
+
const requiredQuestions = [];
|
|
42383
|
+
const target = pendo.dom.getBody();
|
|
42384
|
+
const config = {
|
|
42223
42385
|
attributeFilter: ['data-layout'],
|
|
42224
42386
|
attributes: true,
|
|
42225
42387
|
childList: true,
|
|
42226
42388
|
characterData: true,
|
|
42227
42389
|
subtree: true
|
|
42228
42390
|
};
|
|
42229
|
-
|
|
42230
|
-
|
|
42391
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42392
|
+
const observer = new MutationObserver(applyRequiredIndicators);
|
|
42231
42393
|
observer.observe(target, config);
|
|
42232
42394
|
function applyRequiredIndicators(mutations) {
|
|
42233
42395
|
pendo._.each(mutations, function (mutation) {
|
|
42234
42396
|
var _a;
|
|
42235
|
-
|
|
42397
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
42236
42398
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
42237
|
-
|
|
42399
|
+
let eligiblePolls = mutation.addedNodes[0].querySelectorAll('[class*=-poll-wrapper], [class*=-poll-select-border], [id^=survey-item-wrapper__]');
|
|
42238
42400
|
if (eligiblePolls) {
|
|
42239
42401
|
pendo._.each(eligiblePolls, function (poll) {
|
|
42240
|
-
|
|
42402
|
+
let dataPendoPollId;
|
|
42241
42403
|
if (poll.classList.contains('_pendo-open-text-poll-wrapper') ||
|
|
42242
42404
|
poll.classList.contains('_pendo-number-scale-poll-wrapper')) {
|
|
42243
42405
|
dataPendoPollId = poll.getAttribute('name');
|
|
@@ -42245,31 +42407,31 @@ var RequiredQuestions = {
|
|
|
42245
42407
|
else {
|
|
42246
42408
|
dataPendoPollId = poll.getAttribute('data-pendo-poll-id');
|
|
42247
42409
|
}
|
|
42248
|
-
|
|
42249
|
-
|
|
42250
|
-
pendo.dom(
|
|
42410
|
+
let questionText;
|
|
42411
|
+
const questionElement = pendo.dom(`[class*="-poll-question"][data-pendo-poll-id=${dataPendoPollId}]`)[0] ||
|
|
42412
|
+
pendo.dom(`.bb-text[data-pendo-poll-id=${dataPendoPollId}]`)[0];
|
|
42251
42413
|
if (questionElement) {
|
|
42252
42414
|
questionText = questionElement.textContent;
|
|
42253
42415
|
}
|
|
42254
|
-
|
|
42416
|
+
const requiredSyntaxIndex = questionText ? questionText.indexOf(requiredSyntax) : -1;
|
|
42255
42417
|
if (requiredSyntaxIndex > -1) {
|
|
42256
|
-
pendo._.each(pendo.dom(
|
|
42257
|
-
pendo._.each(pendo.dom(
|
|
42418
|
+
pendo._.each(pendo.dom(`[data-pendo-poll-id=${dataPendoPollId}]:not(.pendo-radio)`), (element) => {
|
|
42419
|
+
pendo._.each(pendo.dom(`#${element.id} *:not(".pendo-radio"), #${element.id}:not(".pendo-radio")`), (item) => {
|
|
42258
42420
|
guideMarkdownUtil.removeMarkdownSyntax(item, requiredSyntax, '', pendo);
|
|
42259
42421
|
});
|
|
42260
42422
|
});
|
|
42261
|
-
|
|
42262
|
-
|
|
42263
|
-
|
|
42264
|
-
|
|
42265
|
-
pendo._.each(pendo.dom(
|
|
42266
|
-
pendo._.each(el.childNodes,
|
|
42423
|
+
const pollTextSelector = `.bb-text[data-pendo-poll-id=${dataPendoPollId}]`;
|
|
42424
|
+
const pollParagraphSelector = `${pollTextSelector} p`;
|
|
42425
|
+
const pollListItemSelector = `${pollTextSelector} li`;
|
|
42426
|
+
const pollIndicatorSelector = `${pollTextSelector} ._pendo-required-indicator`;
|
|
42427
|
+
pendo._.each(pendo.dom(`${pollParagraphSelector}, ${pollListItemSelector}`), (el) => {
|
|
42428
|
+
pendo._.each(el.childNodes, (node) => {
|
|
42267
42429
|
if (node.nodeType === 3 && node.nodeValue.indexOf(requiredSyntax) !== -1) {
|
|
42268
42430
|
node.nodeValue = node.nodeValue.split(requiredSyntax).join('');
|
|
42269
42431
|
}
|
|
42270
42432
|
});
|
|
42271
42433
|
});
|
|
42272
|
-
|
|
42434
|
+
const hasIndicator = pendo.dom(pollIndicatorSelector).length !== 0;
|
|
42273
42435
|
if (!hasIndicator) {
|
|
42274
42436
|
if (pendo.dom(pollParagraphSelector).length !== 0 || pendo.dom(pollListItemSelector).length !== 0) {
|
|
42275
42437
|
pendo.dom(pollParagraphSelector).append(requiredElement);
|
|
@@ -42280,7 +42442,7 @@ var RequiredQuestions = {
|
|
|
42280
42442
|
}
|
|
42281
42443
|
}
|
|
42282
42444
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
42283
|
-
|
|
42445
|
+
let questionIndex = requiredQuestions.indexOf(dataPendoPollId);
|
|
42284
42446
|
if (questionIndex !== -1) {
|
|
42285
42447
|
requiredQuestions.splice(questionIndex, 1);
|
|
42286
42448
|
}
|
|
@@ -42291,7 +42453,7 @@ var RequiredQuestions = {
|
|
|
42291
42453
|
}
|
|
42292
42454
|
else {
|
|
42293
42455
|
if (pendo._.contains(requiredQuestions, dataPendoPollId)) {
|
|
42294
|
-
|
|
42456
|
+
let index = requiredQuestions.indexOf(dataPendoPollId);
|
|
42295
42457
|
if (index !== -1) {
|
|
42296
42458
|
requiredQuestions.splice(index, 1);
|
|
42297
42459
|
}
|
|
@@ -42305,54 +42467,54 @@ var RequiredQuestions = {
|
|
|
42305
42467
|
}
|
|
42306
42468
|
};
|
|
42307
42469
|
|
|
42308
|
-
|
|
42309
|
-
|
|
42310
|
-
script
|
|
42311
|
-
|
|
42312
|
-
|
|
42313
|
-
|
|
42314
|
-
|
|
42315
|
-
|
|
42470
|
+
const skipStepRegex = new RegExp(guideMarkdownUtil.skipStepString);
|
|
42471
|
+
const SkipToEligibleStep = {
|
|
42472
|
+
script(step, guide, pendo) {
|
|
42473
|
+
let isAdvanceIntercepted = false;
|
|
42474
|
+
let isPreviousIntercepted = false;
|
|
42475
|
+
let guideContainer = step.guideElement.find(guideMarkdownUtil.containerSelector);
|
|
42476
|
+
let guideContainerAriaLabel = guideContainer.attr('aria-label');
|
|
42477
|
+
let stepNumberOrAuto = skipStepRegex.exec(guideContainerAriaLabel)[1];
|
|
42316
42478
|
if (guideContainer) {
|
|
42317
42479
|
guideContainer.attr({ 'aria-label': guideContainer.attr('aria-label').replace(skipStepRegex, '') });
|
|
42318
42480
|
}
|
|
42319
|
-
this.on('beforeAdvance',
|
|
42481
|
+
this.on('beforeAdvance', (evt) => {
|
|
42320
42482
|
if (guide.getPositionOfStep(step) === guide.steps.length || pendo._.isUndefined(stepNumberOrAuto))
|
|
42321
42483
|
return; // exit on the last step of a guide or when we don't have an argument
|
|
42322
|
-
|
|
42484
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'next');
|
|
42323
42485
|
if (!isAdvanceIntercepted && stepNumberOrAuto) {
|
|
42324
42486
|
isAdvanceIntercepted = true;
|
|
42325
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42487
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
42326
42488
|
evt.cancel = true;
|
|
42327
42489
|
}
|
|
42328
42490
|
});
|
|
42329
|
-
this.on('beforePrevious',
|
|
42491
|
+
this.on('beforePrevious', (evt) => {
|
|
42330
42492
|
if (pendo._.isUndefined(stepNumberOrAuto))
|
|
42331
42493
|
return;
|
|
42332
|
-
|
|
42494
|
+
let eligibleStep = findEligibleSkipStep(stepNumberOrAuto, 'previous');
|
|
42333
42495
|
if (!isPreviousIntercepted && stepNumberOrAuto) {
|
|
42334
42496
|
isPreviousIntercepted = true;
|
|
42335
|
-
pendo.goToStep({ destinationStepId: eligibleStep.id, step
|
|
42497
|
+
pendo.goToStep({ destinationStepId: eligibleStep.id, step });
|
|
42336
42498
|
evt.cancel = true;
|
|
42337
42499
|
}
|
|
42338
42500
|
});
|
|
42339
42501
|
function findEligibleSkipStep(stepNumber, direction) {
|
|
42340
42502
|
// Find the next eligible step by using getPosition of step (1 based)
|
|
42341
42503
|
// getPosition - 2 gives the previous step
|
|
42342
|
-
|
|
42343
|
-
|
|
42504
|
+
let skipForwardStep = findStepOnPage(guide.getPositionOfStep(step), 'next', stepNumber);
|
|
42505
|
+
let skipPreviousStep = findStepOnPage(guide.getPositionOfStep(step) - 2, 'previous', stepNumber);
|
|
42344
42506
|
if (skipForwardStep && direction == 'next') {
|
|
42345
|
-
pendo.goToStep({ destinationStepId: skipForwardStep, step
|
|
42507
|
+
pendo.goToStep({ destinationStepId: skipForwardStep, step });
|
|
42346
42508
|
}
|
|
42347
42509
|
if (skipPreviousStep && direction == 'previous') {
|
|
42348
|
-
pendo.goToStep({ destinationStepId: skipPreviousStep, step
|
|
42510
|
+
pendo.goToStep({ destinationStepId: skipPreviousStep, step });
|
|
42349
42511
|
}
|
|
42350
42512
|
return direction === 'next' ? skipForwardStep : skipPreviousStep;
|
|
42351
42513
|
}
|
|
42352
42514
|
function findStepOnPage(stepIndex, direction, stepNumber) {
|
|
42353
42515
|
if (pendo._.isNaN(stepIndex))
|
|
42354
42516
|
return;
|
|
42355
|
-
|
|
42517
|
+
let $step = guide.steps[stepIndex];
|
|
42356
42518
|
if ($step && !$step.canShow()) {
|
|
42357
42519
|
if (stepNumber !== 'auto') {
|
|
42358
42520
|
return guide.steps[stepNumber - 1];
|
|
@@ -42369,34 +42531,34 @@ var SkipToEligibleStep = {
|
|
|
42369
42531
|
}
|
|
42370
42532
|
}
|
|
42371
42533
|
},
|
|
42372
|
-
test
|
|
42534
|
+
test(step, guide, pendo) {
|
|
42373
42535
|
var _a;
|
|
42374
|
-
|
|
42536
|
+
const guideContainerAriaLabel = (_a = step.guideElement) === null || _a === void 0 ? void 0 : _a.find(guideMarkdownUtil.containerSelector).attr('aria-label');
|
|
42375
42537
|
return pendo._.isString(guideContainerAriaLabel) && guideContainerAriaLabel.indexOf('{skipStep') !== -1;
|
|
42376
42538
|
},
|
|
42377
|
-
designerListener
|
|
42378
|
-
|
|
42379
|
-
|
|
42539
|
+
designerListener(pendo) {
|
|
42540
|
+
const target = pendo.dom.getBody();
|
|
42541
|
+
const config = {
|
|
42380
42542
|
attributeFilter: ['data-layout'],
|
|
42381
42543
|
attributes: true,
|
|
42382
42544
|
childList: true,
|
|
42383
42545
|
characterData: true,
|
|
42384
42546
|
subtree: true
|
|
42385
42547
|
};
|
|
42386
|
-
|
|
42387
|
-
|
|
42548
|
+
const MutationObserver = getZoneSafeMethod(pendo._, 'MutationObserver');
|
|
42549
|
+
const observer = new MutationObserver(applySkipStepIndicator);
|
|
42388
42550
|
observer.observe(target, config);
|
|
42389
42551
|
// create an observer instance
|
|
42390
42552
|
function applySkipStepIndicator(mutations) {
|
|
42391
42553
|
pendo._.each(mutations, function (mutation) {
|
|
42392
42554
|
var _a, _b;
|
|
42393
|
-
|
|
42555
|
+
const nodeHasQuerySelector = pendo._.isFunction((_a = mutation.addedNodes[0]) === null || _a === void 0 ? void 0 : _a.querySelectorAll);
|
|
42394
42556
|
if (mutation.addedNodes.length && nodeHasQuerySelector) {
|
|
42395
|
-
|
|
42396
|
-
|
|
42557
|
+
let guideContainer = mutation.addedNodes[0].querySelectorAll(guideMarkdownUtil.containerSelector);
|
|
42558
|
+
let guideContainerAriaLabel = (_b = guideContainer[0]) === null || _b === void 0 ? void 0 : _b.getAttribute('aria-label');
|
|
42397
42559
|
if (guideContainerAriaLabel) {
|
|
42398
42560
|
if (guideContainerAriaLabel.match(skipStepRegex)) {
|
|
42399
|
-
|
|
42561
|
+
let fullSkipStepString = guideContainerAriaLabel.match(skipStepRegex)[0];
|
|
42400
42562
|
guideContainerAriaLabel.replace(fullSkipStepString, '');
|
|
42401
42563
|
if (!pendo.dom('#_pendoSkipIcon').length) {
|
|
42402
42564
|
pendo.dom(guideMarkdownUtil.containerSelector).append(skipIcon('#999', '30px').trim());
|
|
@@ -42407,30 +42569,48 @@ var SkipToEligibleStep = {
|
|
|
42407
42569
|
});
|
|
42408
42570
|
}
|
|
42409
42571
|
function skipIcon(color, size) {
|
|
42410
|
-
return (
|
|
42572
|
+
return (`<div title="Skip step added"><svg id="_pendoSkipIcon" version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
42573
|
+
width="${size}" height="${size}" viewBox="0 0 512.000000 512.000000"
|
|
42574
|
+
preserveAspectRatio="xMidYMid meet" style="bottom:5px; right:10px; position: absolute;">
|
|
42575
|
+
<g transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
|
|
42576
|
+
fill="${color}" stroke="none">
|
|
42577
|
+
<path d="M2185 4469 c-363 -38 -739 -186 -1034 -407 -95 -71 -273 -243 -357
|
|
42578
|
+
-343 -205 -246 -364 -577 -429 -897 -25 -121 -45 -288 -45 -373 l0 -49 160 0
|
|
42579
|
+
160 0 0 48 c0 26 5 88 10 137 68 593 417 1103 940 1374 1100 570 2418 -137
|
|
42580
|
+
2560 -1374 5 -49 10 -111 10 -137 l0 -47 -155 -3 -155 -3 235 -235 235 -236
|
|
42581
|
+
235 236 235 235 -155 3 -155 3 0 48 c0 27 -5 95 -10 152 -100 989 -878 1767
|
|
42582
|
+
-1869 1868 -117 12 -298 12 -416 0z"/>
|
|
42583
|
+
<path d="M320 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42584
|
+
<path d="M960 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42585
|
+
<path d="M1600 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42586
|
+
<path d="M2240 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42587
|
+
<path d="M2880 1440 l0 -160 160 0 160 0 0 160 0 160 -160 0 -160 0 0 -160z"/>
|
|
42588
|
+
<path d="M3840 1440 l0 -160 480 0 480 0 0 160 0 160 -480 0 -480 0 0 -160z"/>
|
|
42589
|
+
</g></svg></div>
|
|
42590
|
+
`);
|
|
42411
42591
|
}
|
|
42412
42592
|
}
|
|
42413
42593
|
};
|
|
42414
42594
|
|
|
42415
42595
|
function GuideMarkdown() {
|
|
42416
|
-
|
|
42417
|
-
|
|
42418
|
-
|
|
42596
|
+
let guideMarkdown;
|
|
42597
|
+
let pluginApi;
|
|
42598
|
+
let globalPendo;
|
|
42419
42599
|
return {
|
|
42420
42600
|
name: 'GuideMarkdown',
|
|
42421
42601
|
initialize: init,
|
|
42422
|
-
teardown
|
|
42602
|
+
teardown
|
|
42423
42603
|
};
|
|
42424
42604
|
function init(pendo, PluginAPI) {
|
|
42425
42605
|
globalPendo = pendo;
|
|
42426
42606
|
pluginApi = PluginAPI;
|
|
42427
|
-
|
|
42428
|
-
|
|
42607
|
+
const configReader = PluginAPI.ConfigReader;
|
|
42608
|
+
const GUIDEMARKDOWN_CONFIG = 'guideMarkdown';
|
|
42429
42609
|
configReader.addOption(GUIDEMARKDOWN_CONFIG, [
|
|
42430
42610
|
configReader.sources.SNIPPET_SRC,
|
|
42431
42611
|
configReader.sources.PENDO_CONFIG_SRC
|
|
42432
42612
|
], false);
|
|
42433
|
-
|
|
42613
|
+
const markdownScriptsEnabled = configReader.get(GUIDEMARKDOWN_CONFIG);
|
|
42434
42614
|
if (!markdownScriptsEnabled)
|
|
42435
42615
|
return;
|
|
42436
42616
|
guideMarkdown = [PollBranching, MetadataSubstitution, RequiredQuestions, SkipToEligibleStep];
|
|
@@ -43489,8 +43669,8 @@ function Feedback() {
|
|
|
43489
43669
|
var widgetLoaded = false;
|
|
43490
43670
|
var feedbackAllowedProductId = '';
|
|
43491
43671
|
var initialized = false;
|
|
43492
|
-
|
|
43493
|
-
|
|
43672
|
+
const PING_COOKIE = 'feedback_ping_sent';
|
|
43673
|
+
const PING_COOKIE_EXPIRATION = 1000 * 60 * 60;
|
|
43494
43674
|
var overflowMediaQuery = '@media only screen and (max-device-width:1112px){#feedback-widget{overflow-y:scroll}}';
|
|
43495
43675
|
var slideIn = '@-webkit-keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}@keyframes pendoFeedbackSlideIn{from{opacity:0;transform:translate(145px,0) rotate(270deg) translateY(-50%)}to{opacity:1;transform:translate(50%,0) rotate(270deg) translateY(-50%)}}';
|
|
43496
43676
|
var slideInLeft = '@-webkit-keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}@keyframes pendoFeedbackSlideIn-left{from{opacity:0;transform:rotate(270deg) translateX(-55%) translateY(-55%)}to{opacity:1;transform:rotate(270deg) translateX(-55%) translateY(0)}}';
|
|
@@ -43510,28 +43690,28 @@ function Feedback() {
|
|
|
43510
43690
|
feedbackStyles: 'pendo-feedback-styles',
|
|
43511
43691
|
feedbackFrameStyles: 'pendo-feedback-visible-buttons-styles'
|
|
43512
43692
|
};
|
|
43513
|
-
|
|
43514
|
-
|
|
43693
|
+
let globalPendo;
|
|
43694
|
+
let pluginApi;
|
|
43515
43695
|
return {
|
|
43516
43696
|
name: 'Feedback',
|
|
43517
|
-
initialize
|
|
43518
|
-
teardown
|
|
43519
|
-
validate
|
|
43697
|
+
initialize,
|
|
43698
|
+
teardown,
|
|
43699
|
+
validate
|
|
43520
43700
|
};
|
|
43521
43701
|
function initialize(pendo, PluginAPI) {
|
|
43522
43702
|
globalPendo = pendo;
|
|
43523
43703
|
pluginApi = PluginAPI;
|
|
43524
43704
|
var publicFeedback = {
|
|
43525
|
-
ping
|
|
43526
|
-
init
|
|
43705
|
+
ping,
|
|
43706
|
+
init,
|
|
43527
43707
|
initialized: getInitialized,
|
|
43528
|
-
loginAndRedirect
|
|
43529
|
-
openFeedback
|
|
43530
|
-
initializeFeedbackOnce
|
|
43531
|
-
isFeedbackLoaded
|
|
43532
|
-
convertPendoToFeedbackOptions
|
|
43708
|
+
loginAndRedirect,
|
|
43709
|
+
openFeedback,
|
|
43710
|
+
initializeFeedbackOnce,
|
|
43711
|
+
isFeedbackLoaded,
|
|
43712
|
+
convertPendoToFeedbackOptions,
|
|
43533
43713
|
isUnsupportedIE: pendo._.partial(isUnsupportedIE, PluginAPI),
|
|
43534
|
-
removeFeedbackWidget
|
|
43714
|
+
removeFeedbackWidget
|
|
43535
43715
|
};
|
|
43536
43716
|
pendo.feedback = publicFeedback;
|
|
43537
43717
|
pendo.getFeedbackSettings = getFeedbackSettings;
|
|
@@ -43562,7 +43742,7 @@ function Feedback() {
|
|
|
43562
43742
|
localStorageOnly: true
|
|
43563
43743
|
});
|
|
43564
43744
|
return {
|
|
43565
|
-
validate
|
|
43745
|
+
validate
|
|
43566
43746
|
};
|
|
43567
43747
|
}
|
|
43568
43748
|
function teardown() {
|
|
@@ -43582,18 +43762,18 @@ function Feedback() {
|
|
|
43582
43762
|
return result;
|
|
43583
43763
|
}
|
|
43584
43764
|
function pingOrInitialize() {
|
|
43585
|
-
|
|
43765
|
+
const options = getPendoOptions();
|
|
43586
43766
|
if (initialized) {
|
|
43587
|
-
|
|
43767
|
+
const feedbackOptions = convertPendoToFeedbackOptions(options);
|
|
43588
43768
|
ping(feedbackOptions);
|
|
43589
43769
|
}
|
|
43590
43770
|
else if (shouldInitializeFeedback() && !globalPendo._.isEmpty(options)) {
|
|
43591
|
-
|
|
43592
|
-
init(options, settings)
|
|
43771
|
+
const settings = pluginApi.ConfigReader.get('feedbackSettings');
|
|
43772
|
+
init(options, settings).catch(globalPendo._.noop);
|
|
43593
43773
|
}
|
|
43594
43774
|
}
|
|
43595
43775
|
function handleIdentityChange(event) {
|
|
43596
|
-
|
|
43776
|
+
const visitorId = globalPendo._.get(event, 'data.0.visitor_id') || globalPendo._.get(event, 'data.0.options.visitor.id');
|
|
43597
43777
|
if (globalPendo.isAnonymousVisitor(visitorId)) {
|
|
43598
43778
|
removeFeedbackWidget();
|
|
43599
43779
|
return;
|
|
@@ -43663,9 +43843,9 @@ function Feedback() {
|
|
|
43663
43843
|
if (toSend.data && toSend.data !== '{}' && toSend.data !== 'null') {
|
|
43664
43844
|
return globalPendo.ajax
|
|
43665
43845
|
.postJSON(getFullUrl('/widget/pendo_ping'), toSend)
|
|
43666
|
-
.then(
|
|
43846
|
+
.then((response) => {
|
|
43667
43847
|
onWidgetPingResponse(response);
|
|
43668
|
-
})
|
|
43848
|
+
}).catch(() => { onPingFailure(); });
|
|
43669
43849
|
}
|
|
43670
43850
|
}
|
|
43671
43851
|
return pluginApi.q.resolve();
|
|
@@ -43799,10 +43979,10 @@ function Feedback() {
|
|
|
43799
43979
|
return globalPendo.ajax.postJSON(getFullUrl('/analytics'), toSend);
|
|
43800
43980
|
}
|
|
43801
43981
|
function addOverlay() {
|
|
43802
|
-
|
|
43982
|
+
const widget = globalPendo.dom(`#${elemIds.feedbackWidget}`);
|
|
43803
43983
|
if (!widget)
|
|
43804
43984
|
return;
|
|
43805
|
-
|
|
43985
|
+
const overlayStyles = {
|
|
43806
43986
|
'position': 'fixed',
|
|
43807
43987
|
'top': '0',
|
|
43808
43988
|
'right': '0',
|
|
@@ -43814,7 +43994,7 @@ function Feedback() {
|
|
|
43814
43994
|
'animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both',
|
|
43815
43995
|
'-webkit-animation': 'pendoFeedbackFadeIn 0.5s 0s 1 alternate both'
|
|
43816
43996
|
};
|
|
43817
|
-
|
|
43997
|
+
const overlayElement = globalPendo.dom(document.createElement('div'));
|
|
43818
43998
|
overlayElement.attr('id', 'feedback-overlay');
|
|
43819
43999
|
overlayElement.css(overlayStyles);
|
|
43820
44000
|
overlayElement.appendTo(widget.getParent());
|
|
@@ -43919,22 +44099,22 @@ function Feedback() {
|
|
|
43919
44099
|
}
|
|
43920
44100
|
}
|
|
43921
44101
|
function buildOuterTriggerDiv(positionInfo) {
|
|
43922
|
-
|
|
43923
|
-
|
|
43924
|
-
|
|
44102
|
+
const horizontalStyles = getHorizontalPositionStyles(positionInfo);
|
|
44103
|
+
const verticalStyles = getVerticalPositionStyles(positionInfo);
|
|
44104
|
+
const styles = globalPendo._.extend({
|
|
43925
44105
|
'position': 'fixed',
|
|
43926
44106
|
'height': '43px',
|
|
43927
44107
|
'opacity': '1 !important',
|
|
43928
44108
|
'z-index': '9001'
|
|
43929
44109
|
}, horizontalStyles, verticalStyles);
|
|
43930
|
-
|
|
44110
|
+
const outerTrigger = globalPendo.dom(document.createElement('div'));
|
|
43931
44111
|
outerTrigger.attr('id', elemIds.feedbackTrigger);
|
|
43932
44112
|
outerTrigger.css(styles);
|
|
43933
44113
|
outerTrigger.attr('data-turbolinks-permanent', '');
|
|
43934
44114
|
return outerTrigger;
|
|
43935
44115
|
}
|
|
43936
44116
|
function buildNotification() {
|
|
43937
|
-
|
|
44117
|
+
const styles = {
|
|
43938
44118
|
'background-color': '#D85039',
|
|
43939
44119
|
'color': '#fff',
|
|
43940
44120
|
'border-radius': '50%',
|
|
@@ -43951,20 +44131,20 @@ function Feedback() {
|
|
|
43951
44131
|
'animation-delay': '1s',
|
|
43952
44132
|
'animation-iteration-count': '1'
|
|
43953
44133
|
};
|
|
43954
|
-
|
|
44134
|
+
const notification = globalPendo.dom(document.createElement('span'));
|
|
43955
44135
|
notification.attr('id', 'feedback-trigger-notification');
|
|
43956
44136
|
notification.css(styles);
|
|
43957
44137
|
return notification;
|
|
43958
44138
|
}
|
|
43959
44139
|
function buildTriggerButton(settings, positionInfo) {
|
|
43960
|
-
|
|
44140
|
+
let borderRadius;
|
|
43961
44141
|
if (positionInfo.horizontalPosition === 'left') {
|
|
43962
44142
|
borderRadius = '0 0 5px 5px';
|
|
43963
44143
|
}
|
|
43964
44144
|
else {
|
|
43965
44145
|
borderRadius = '3px 3px 0 0';
|
|
43966
44146
|
}
|
|
43967
|
-
|
|
44147
|
+
const styles = {
|
|
43968
44148
|
'border': 'none',
|
|
43969
44149
|
'padding': '11px 18px 14px 18px',
|
|
43970
44150
|
'background-color': settings.triggerColor,
|
|
@@ -43975,21 +44155,32 @@ function Feedback() {
|
|
|
43975
44155
|
'cursor': 'pointer',
|
|
43976
44156
|
'text-align': 'left'
|
|
43977
44157
|
};
|
|
43978
|
-
|
|
44158
|
+
const triggerButton = globalPendo.dom(document.createElement('button'));
|
|
43979
44159
|
triggerButton.attr('id', elemIds.feedbackTriggerButton);
|
|
43980
44160
|
triggerButton.css(styles);
|
|
43981
44161
|
triggerButton.text(settings.triggerText);
|
|
43982
44162
|
return triggerButton;
|
|
43983
44163
|
}
|
|
43984
44164
|
function addTriggerPseudoStyles() {
|
|
43985
|
-
|
|
44165
|
+
const pseudoStyles = `
|
|
44166
|
+
#feedback-trigger button:hover {
|
|
44167
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
44168
|
+
outline: none !important;
|
|
44169
|
+
background: #3e566f !important;
|
|
44170
|
+
}
|
|
44171
|
+
#feedback-trigger button:focus {
|
|
44172
|
+
box-shadow: 0 -5px 20px rgba(0,0,0,.19) !important;
|
|
44173
|
+
outline: none !important;
|
|
44174
|
+
background: #3e566f !important;
|
|
44175
|
+
}
|
|
44176
|
+
`;
|
|
43986
44177
|
pluginApi.util.addInlineStyles('pendo-feedback-trigger-styles', pseudoStyles);
|
|
43987
44178
|
}
|
|
43988
44179
|
function createTrigger(settings, positionInfo) {
|
|
43989
44180
|
addTriggerPseudoStyles();
|
|
43990
|
-
|
|
43991
|
-
|
|
43992
|
-
|
|
44181
|
+
const triggerElement = buildOuterTriggerDiv(positionInfo);
|
|
44182
|
+
const notificationElement = buildNotification();
|
|
44183
|
+
const triggerButtonElement = buildTriggerButton(settings, positionInfo);
|
|
43993
44184
|
triggerElement.append(notificationElement);
|
|
43994
44185
|
triggerElement.append(triggerButtonElement);
|
|
43995
44186
|
triggerElement.appendTo(globalPendo.dom.getBody());
|
|
@@ -44013,7 +44204,7 @@ function Feedback() {
|
|
|
44013
44204
|
iframeWrapper.css(getWidgetOriginalStyles());
|
|
44014
44205
|
iframeWrapper.attr('id', elemIds.feedbackWidget);
|
|
44015
44206
|
iframeWrapper.attr('data-turbolinks-permanent', 'true');
|
|
44016
|
-
iframeWrapper.addClass(
|
|
44207
|
+
iframeWrapper.addClass(`buttonIs-${horizontalPosition}`);
|
|
44017
44208
|
return iframeWrapper;
|
|
44018
44209
|
}
|
|
44019
44210
|
function buildIframeContainer() {
|
|
@@ -44030,13 +44221,22 @@ function Feedback() {
|
|
|
44030
44221
|
return iframeContainer;
|
|
44031
44222
|
}
|
|
44032
44223
|
function addWidgetVisibleButtonStyles(buttonStylePosition) {
|
|
44033
|
-
|
|
44034
|
-
|
|
44224
|
+
let side = buttonStylePosition === 'left' ? 'left' : 'right'; // just in case something was not left or right for some reason
|
|
44225
|
+
const styles = `
|
|
44226
|
+
.buttonIs-${side}.visible {
|
|
44227
|
+
${side}: 0 !important;
|
|
44228
|
+
width: 470px !important;
|
|
44229
|
+
animation-direction: alternate-reverse !important;
|
|
44230
|
+
animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
44231
|
+
-webkit-animation: pendoFeedbackSlideFrom-${side} 0.5s 0s 1 alternate both !important;
|
|
44232
|
+
z-index: 9002 !important;
|
|
44233
|
+
}
|
|
44234
|
+
`;
|
|
44035
44235
|
pluginApi.util.addInlineStyles(elemIds.feedbackFrameStyles, styles);
|
|
44036
44236
|
}
|
|
44037
44237
|
function initialiseWidgetFrame(horizontalPosition) {
|
|
44038
44238
|
addWidgetVisibleButtonStyles(horizontalPosition);
|
|
44039
|
-
|
|
44239
|
+
const iframeElement = buildIframeWrapper(horizontalPosition);
|
|
44040
44240
|
iframeElement.append(buildIframeContainer());
|
|
44041
44241
|
iframeElement.appendTo(globalPendo.dom.getBody());
|
|
44042
44242
|
subscribeToIframeMessages();
|
|
@@ -44060,7 +44260,7 @@ function Feedback() {
|
|
|
44060
44260
|
return widgetLoaded;
|
|
44061
44261
|
}
|
|
44062
44262
|
function getPendoOptions() {
|
|
44063
|
-
|
|
44263
|
+
let options = pluginApi.ConfigReader.getLocalConfig();
|
|
44064
44264
|
if (!globalPendo._.isObject(options))
|
|
44065
44265
|
options = {};
|
|
44066
44266
|
if (!globalPendo._.isObject(options.visitor))
|
|
@@ -44088,7 +44288,7 @@ function Feedback() {
|
|
|
44088
44288
|
return true;
|
|
44089
44289
|
}
|
|
44090
44290
|
function getQueryParam(url, paramName) {
|
|
44091
|
-
|
|
44291
|
+
const results = new RegExp('[?&]' + paramName + '=([^&#]*)').exec(url);
|
|
44092
44292
|
if (results == null) {
|
|
44093
44293
|
return null;
|
|
44094
44294
|
}
|
|
@@ -44105,13 +44305,13 @@ function Feedback() {
|
|
|
44105
44305
|
return pluginApi.q.reject();
|
|
44106
44306
|
if (!canInitFeedback(pendoOptions))
|
|
44107
44307
|
return pluginApi.q.reject();
|
|
44108
|
-
|
|
44308
|
+
const feedbackOptions = convertPendoToFeedbackOptions(pendoOptions);
|
|
44109
44309
|
try {
|
|
44110
|
-
|
|
44111
|
-
if (
|
|
44310
|
+
const fdbkDst = getQueryParam(globalPendo.url.get(), 'fdbkDst');
|
|
44311
|
+
if (fdbkDst && fdbkDst.startsWith('case')) {
|
|
44112
44312
|
initialized = true;
|
|
44113
44313
|
getFeedbackLoginUrl().then(function (loginUrl) {
|
|
44114
|
-
|
|
44314
|
+
const destinationUrl = loginUrl + '&fdbkDst=' + fdbkDst;
|
|
44115
44315
|
window.location.href = destinationUrl;
|
|
44116
44316
|
});
|
|
44117
44317
|
return;
|
|
@@ -44160,7 +44360,7 @@ function Feedback() {
|
|
|
44160
44360
|
function convertPendoToFeedbackOptions(options) {
|
|
44161
44361
|
var jwtOptions = pluginApi.agent.getJwtInfoCopy();
|
|
44162
44362
|
if (globalPendo._.isEmpty(jwtOptions)) {
|
|
44163
|
-
|
|
44363
|
+
const feedbackOptions = {};
|
|
44164
44364
|
feedbackOptions.user = globalPendo._.pick(options.visitor, 'id', 'full_name', 'firstName', 'lastName', 'email', 'tags', 'custom_allowed_products');
|
|
44165
44365
|
globalPendo._.extend(feedbackOptions.user, { allowed_products: [{ id: feedbackAllowedProductId }] });
|
|
44166
44366
|
feedbackOptions.account = globalPendo._.pick(options.account, 'id', 'name', 'monthly_value', 'is_paying', 'tags');
|
|
@@ -49695,32 +49895,31 @@ var n;
|
|
|
49695
49895
|
}(n || (n = {}));
|
|
49696
49896
|
return record; }
|
|
49697
49897
|
|
|
49698
|
-
|
|
49699
|
-
|
|
49700
|
-
if (maxCount === void 0) { maxCount = Infinity; }
|
|
49898
|
+
class SessionRecorderBuffer {
|
|
49899
|
+
constructor(interval, maxCount = Infinity) {
|
|
49701
49900
|
this.data = [];
|
|
49702
49901
|
this.sequenceNumber = 0;
|
|
49703
49902
|
this.interval = interval;
|
|
49704
49903
|
this.maxCount = maxCount;
|
|
49705
49904
|
this.doubledMaxCount = maxCount * 2;
|
|
49706
49905
|
}
|
|
49707
|
-
|
|
49906
|
+
isEmpty() {
|
|
49708
49907
|
return this.data.length === 0;
|
|
49709
|
-
}
|
|
49710
|
-
|
|
49908
|
+
}
|
|
49909
|
+
count() {
|
|
49711
49910
|
return this.data.length;
|
|
49712
|
-
}
|
|
49713
|
-
|
|
49911
|
+
}
|
|
49912
|
+
clear() {
|
|
49714
49913
|
this.data.length = 0;
|
|
49715
|
-
}
|
|
49716
|
-
|
|
49914
|
+
}
|
|
49915
|
+
clearSequence() {
|
|
49717
49916
|
this.sequenceNumber = 0;
|
|
49718
|
-
}
|
|
49719
|
-
|
|
49917
|
+
}
|
|
49918
|
+
push(event) {
|
|
49720
49919
|
this.data.push(event);
|
|
49721
49920
|
this.checkRateLimit();
|
|
49722
|
-
}
|
|
49723
|
-
|
|
49921
|
+
}
|
|
49922
|
+
pack(envelope, _) {
|
|
49724
49923
|
var eventsToSend = this.data.splice(0, this.maxCount);
|
|
49725
49924
|
envelope.recordingPayload = eventsToSend;
|
|
49726
49925
|
envelope.sequence = this.sequenceNumber;
|
|
@@ -49728,8 +49927,8 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49728
49927
|
if (eventsToSend.length) {
|
|
49729
49928
|
envelope.browserTime = eventsToSend[0].timestamp;
|
|
49730
49929
|
}
|
|
49731
|
-
envelope.recordingPayloadMetadata = _.map(eventsToSend,
|
|
49732
|
-
|
|
49930
|
+
envelope.recordingPayloadMetadata = _.map(eventsToSend, event => {
|
|
49931
|
+
const metadata = _.pick(event, 'type', 'timestamp');
|
|
49733
49932
|
if (event.data) {
|
|
49734
49933
|
metadata.data = _.pick(event.data, 'source', 'type', 'x', 'y', 'id', 'height', 'width', 'href');
|
|
49735
49934
|
}
|
|
@@ -49737,30 +49936,18 @@ var SessionRecorderBuffer = /** @class */ (function () {
|
|
|
49737
49936
|
});
|
|
49738
49937
|
this.sequenceNumber += eventsToSend.length;
|
|
49739
49938
|
return envelope;
|
|
49740
|
-
}
|
|
49741
|
-
|
|
49742
|
-
|
|
49939
|
+
}
|
|
49940
|
+
checkRateLimit() {
|
|
49941
|
+
const length = this.data.length;
|
|
49743
49942
|
if (length >= this.doubledMaxCount && length % this.maxCount === 0) {
|
|
49744
|
-
|
|
49943
|
+
const elapsed = this.data[length - 1].timestamp - this.data[length - this.doubledMaxCount].timestamp;
|
|
49745
49944
|
if (elapsed <= this.interval && this.onRateLimit) {
|
|
49746
49945
|
this.onRateLimit();
|
|
49747
49946
|
}
|
|
49748
49947
|
}
|
|
49749
|
-
}
|
|
49750
|
-
|
|
49751
|
-
}());
|
|
49948
|
+
}
|
|
49949
|
+
}
|
|
49752
49950
|
|
|
49753
|
-
var __assign = function() {
|
|
49754
|
-
__assign = Object.assign || function __assign(t) {
|
|
49755
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
49756
|
-
s = arguments[i];
|
|
49757
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
|
|
49758
|
-
}
|
|
49759
|
-
return t;
|
|
49760
|
-
};
|
|
49761
|
-
return __assign.apply(this, arguments);
|
|
49762
|
-
};
|
|
49763
|
-
|
|
49764
49951
|
function __rest(s, e) {
|
|
49765
49952
|
var t = {};
|
|
49766
49953
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -49783,52 +49970,24 @@ function __awaiter(thisArg, _arguments, P, generator) {
|
|
|
49783
49970
|
});
|
|
49784
49971
|
}
|
|
49785
49972
|
|
|
49786
|
-
function __generator(thisArg, body) {
|
|
49787
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
49788
|
-
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
49789
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
49790
|
-
function step(op) {
|
|
49791
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
49792
|
-
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
49793
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
49794
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
49795
|
-
switch (op[0]) {
|
|
49796
|
-
case 0: case 1: t = op; break;
|
|
49797
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
49798
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
49799
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
49800
|
-
default:
|
|
49801
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
49802
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
49803
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
49804
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
49805
|
-
if (t[2]) _.ops.pop();
|
|
49806
|
-
_.trys.pop(); continue;
|
|
49807
|
-
}
|
|
49808
|
-
op = body.call(thisArg, _);
|
|
49809
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
49810
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
49811
|
-
}
|
|
49812
|
-
}
|
|
49813
|
-
|
|
49814
49973
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
49815
49974
|
var e = new Error(message);
|
|
49816
49975
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
49817
49976
|
};
|
|
49818
49977
|
|
|
49819
|
-
|
|
49820
|
-
|
|
49821
|
-
|
|
49822
|
-
|
|
49823
|
-
|
|
49978
|
+
const RECORDING_CONFIG_WORKERURL$1 = 'recording.workerUrl';
|
|
49979
|
+
const MAX_SIZE = 2000000;
|
|
49980
|
+
const RESOURCE_CACHING$1 = 'resourceCaching';
|
|
49981
|
+
class Transport {
|
|
49982
|
+
constructor(WorkerClass, pendo, api) {
|
|
49824
49983
|
this.WorkerClass = WorkerClass;
|
|
49825
49984
|
this.pendo = pendo;
|
|
49826
49985
|
this.api = api;
|
|
49827
49986
|
this.maxSize = MAX_SIZE;
|
|
49828
|
-
this.lockID =
|
|
49987
|
+
this.lockID = `worker-lock-${this.pendo.randomString(16)}`;
|
|
49829
49988
|
this.isResourceCachingEnabled = this.api.ConfigReader.get(RESOURCE_CACHING$1);
|
|
49830
49989
|
}
|
|
49831
|
-
|
|
49990
|
+
start(config) {
|
|
49832
49991
|
if (config.disableWorker)
|
|
49833
49992
|
return;
|
|
49834
49993
|
if (!this.worker) {
|
|
@@ -49838,7 +49997,7 @@ var Transport = /** @class */ (function () {
|
|
|
49838
49997
|
this.worker = config.workerOverride;
|
|
49839
49998
|
}
|
|
49840
49999
|
else {
|
|
49841
|
-
|
|
50000
|
+
const workerUrl = this.api.ConfigReader.get(RECORDING_CONFIG_WORKERURL$1);
|
|
49842
50001
|
this.usesSelfHostedWorker = workerUrl != null;
|
|
49843
50002
|
this.worker = workerUrl ? new Worker(workerUrl) : new this.WorkerClass();
|
|
49844
50003
|
}
|
|
@@ -49852,35 +50011,34 @@ var Transport = /** @class */ (function () {
|
|
|
49852
50011
|
this.worker = null;
|
|
49853
50012
|
}
|
|
49854
50013
|
}
|
|
49855
|
-
}
|
|
49856
|
-
|
|
50014
|
+
}
|
|
50015
|
+
stop() {
|
|
49857
50016
|
if (this.worker) {
|
|
49858
50017
|
this.worker.terminate();
|
|
49859
50018
|
delete this.worker;
|
|
49860
50019
|
}
|
|
49861
|
-
}
|
|
49862
|
-
|
|
49863
|
-
|
|
49864
|
-
|
|
49865
|
-
var payload = envelope.payload;
|
|
50020
|
+
}
|
|
50021
|
+
send(envelope, isUnload, failureCount = 0) {
|
|
50022
|
+
let { url } = envelope;
|
|
50023
|
+
const { payload } = envelope;
|
|
49866
50024
|
if (failureCount > 0) {
|
|
49867
|
-
url =
|
|
50025
|
+
url = `${url}&rt=${failureCount}`;
|
|
49868
50026
|
}
|
|
49869
50027
|
if (this.worker && !isUnload && payload) {
|
|
49870
|
-
|
|
49871
|
-
|
|
49872
|
-
|
|
49873
|
-
|
|
50028
|
+
const deferred = {};
|
|
50029
|
+
deferred.promise = new Promise$2((resolve, reject) => {
|
|
50030
|
+
deferred.resolve = resolve;
|
|
50031
|
+
deferred.reject = reject;
|
|
49874
50032
|
});
|
|
49875
|
-
this.workerResponse =
|
|
49876
|
-
this.worker.postMessage({ url
|
|
49877
|
-
return
|
|
50033
|
+
this.workerResponse = deferred;
|
|
50034
|
+
this.worker.postMessage({ url, payload, shouldCacheResources: this.isResourceCachingEnabled });
|
|
50035
|
+
return deferred.promise;
|
|
49878
50036
|
}
|
|
49879
50037
|
else {
|
|
49880
50038
|
if (!envelope.body) {
|
|
49881
|
-
|
|
50039
|
+
const strPayload = JSON.stringify(payload);
|
|
49882
50040
|
if (strPayload.length > this.maxSize) {
|
|
49883
|
-
|
|
50041
|
+
const error = new Error('maximum recording payload size exceeded');
|
|
49884
50042
|
error.reason = 'HEAVY_EVENT';
|
|
49885
50043
|
error.context = {
|
|
49886
50044
|
size: strPayload.length,
|
|
@@ -49891,14 +50049,14 @@ var Transport = /** @class */ (function () {
|
|
|
49891
50049
|
envelope.body = this.pendo.compress(strPayload, 'binary');
|
|
49892
50050
|
delete envelope.payload;
|
|
49893
50051
|
}
|
|
49894
|
-
url =
|
|
50052
|
+
url = `${url}&ct=${new Date().getTime()}`;
|
|
49895
50053
|
return this.post(url, {
|
|
49896
50054
|
keepalive: isUnload,
|
|
49897
50055
|
body: envelope.body
|
|
49898
50056
|
});
|
|
49899
50057
|
}
|
|
49900
|
-
}
|
|
49901
|
-
|
|
50058
|
+
}
|
|
50059
|
+
post(url, options) {
|
|
49902
50060
|
options.method = 'POST';
|
|
49903
50061
|
if (options.keepalive && this.api.transmit.fetchKeepalive.supported()) {
|
|
49904
50062
|
return this.api.transmit.fetchKeepalive(url, options);
|
|
@@ -49910,57 +50068,46 @@ var Transport = /** @class */ (function () {
|
|
|
49910
50068
|
else {
|
|
49911
50069
|
return this.pendo.ajax.post(url, options.body);
|
|
49912
50070
|
}
|
|
49913
|
-
}
|
|
49914
|
-
|
|
49915
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
49916
|
-
|
|
49917
|
-
|
|
49918
|
-
|
|
49919
|
-
|
|
49920
|
-
|
|
49921
|
-
|
|
49922
|
-
|
|
49923
|
-
|
|
49924
|
-
|
|
49925
|
-
|
|
49926
|
-
|
|
49927
|
-
|
|
49928
|
-
|
|
49929
|
-
|
|
49930
|
-
|
|
49931
|
-
return [2 /*return*/];
|
|
49932
|
-
}
|
|
49933
|
-
// handle POST request response from worker
|
|
49934
|
-
if (messageEvent.data && messageEvent.data.error) {
|
|
49935
|
-
if ((messageEvent.data.status && messageEvent.data.status < 500) ||
|
|
49936
|
-
messageEvent.data.sequence == null) {
|
|
49937
|
-
this.api.log.critical('Failed to send recording data from web worker', { error: messageEvent.data.error });
|
|
49938
|
-
}
|
|
49939
|
-
if (this.workerResponse) {
|
|
49940
|
-
this.workerResponse.reject();
|
|
49941
|
-
this.workerResponse = null;
|
|
49942
|
-
}
|
|
49943
|
-
}
|
|
49944
|
-
if (this.workerResponse) {
|
|
49945
|
-
this.workerResponse.resolve();
|
|
49946
|
-
this.workerResponse = null;
|
|
49947
|
-
}
|
|
49948
|
-
return [2 /*return*/];
|
|
50071
|
+
}
|
|
50072
|
+
_onMessage(messageEvent) {
|
|
50073
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
50074
|
+
if (messageEvent.data && messageEvent.data.ready && navigator.locks) {
|
|
50075
|
+
// When the lock is released, we can assume the worker was terminated or closed
|
|
50076
|
+
yield navigator.locks.request(this.lockID, () => { });
|
|
50077
|
+
this.onWorkerMessage({ type: 'workerDied' });
|
|
50078
|
+
}
|
|
50079
|
+
// handle non-POST request responses from worker
|
|
50080
|
+
if (messageEvent.data && messageEvent.data.type) {
|
|
50081
|
+
this.onWorkerMessage(messageEvent.data);
|
|
50082
|
+
return;
|
|
50083
|
+
}
|
|
50084
|
+
// handle POST request response from worker
|
|
50085
|
+
if (messageEvent.data && messageEvent.data.error) {
|
|
50086
|
+
if ((messageEvent.data.status && messageEvent.data.status < 500) ||
|
|
50087
|
+
messageEvent.data.sequence == null) {
|
|
50088
|
+
this.api.log.critical('Failed to send recording data from web worker', { error: messageEvent.data.error });
|
|
49949
50089
|
}
|
|
49950
|
-
|
|
50090
|
+
if (this.workerResponse) {
|
|
50091
|
+
this.workerResponse.reject();
|
|
50092
|
+
this.workerResponse = null;
|
|
50093
|
+
}
|
|
50094
|
+
}
|
|
50095
|
+
if (this.workerResponse) {
|
|
50096
|
+
this.workerResponse.resolve();
|
|
50097
|
+
this.workerResponse = null;
|
|
50098
|
+
}
|
|
49951
50099
|
});
|
|
49952
|
-
}
|
|
49953
|
-
|
|
50100
|
+
}
|
|
50101
|
+
_onError() {
|
|
49954
50102
|
if (this.onError) {
|
|
49955
50103
|
this.onError();
|
|
49956
50104
|
}
|
|
49957
|
-
}
|
|
49958
|
-
|
|
49959
|
-
}());
|
|
50105
|
+
}
|
|
50106
|
+
}
|
|
49960
50107
|
|
|
49961
|
-
|
|
49962
|
-
|
|
49963
|
-
|
|
50108
|
+
const ELEMENT_NODE = 1;
|
|
50109
|
+
const INPUT_MASK = '*'.repeat(10);
|
|
50110
|
+
const NUMBER_INPUT_MASK = '0'.repeat(10);
|
|
49964
50111
|
function isElementNode(node) {
|
|
49965
50112
|
if (!node)
|
|
49966
50113
|
return false;
|
|
@@ -49969,12 +50116,10 @@ function isElementNode(node) {
|
|
|
49969
50116
|
return true;
|
|
49970
50117
|
}
|
|
49971
50118
|
function getParent(elem) {
|
|
49972
|
-
|
|
50119
|
+
const isElementShadowRoot = typeof window.ShadowRoot !== 'undefined' && elem instanceof window.ShadowRoot && elem.host;
|
|
49973
50120
|
return isElementShadowRoot ? elem.host : elem.parentNode;
|
|
49974
50121
|
}
|
|
49975
|
-
function distanceToMatch(node, selector, limit, distance) {
|
|
49976
|
-
if (limit === void 0) { limit = Infinity; }
|
|
49977
|
-
if (distance === void 0) { distance = 0; }
|
|
50122
|
+
function distanceToMatch(node, selector, limit = Infinity, distance = 0) {
|
|
49978
50123
|
if (distance > limit)
|
|
49979
50124
|
return -1;
|
|
49980
50125
|
if (!node)
|
|
@@ -49988,15 +50133,15 @@ function distanceToMatch(node, selector, limit, distance) {
|
|
|
49988
50133
|
return distanceToMatch(getParent(node), selector, limit, distance + 1);
|
|
49989
50134
|
}
|
|
49990
50135
|
function shouldMask(node, options) {
|
|
49991
|
-
|
|
50136
|
+
const { maskAllText, maskTextSelector, unmaskTextSelector } = options;
|
|
49992
50137
|
try {
|
|
49993
|
-
|
|
50138
|
+
const el = isElementNode(node) ? node : node.parentElement;
|
|
49994
50139
|
if (el === null)
|
|
49995
50140
|
return false;
|
|
49996
50141
|
if ((el.tagName || '').toUpperCase() === 'STYLE')
|
|
49997
50142
|
return false;
|
|
49998
|
-
|
|
49999
|
-
|
|
50143
|
+
let maskDistance = -1;
|
|
50144
|
+
let unmaskDistance = -1;
|
|
50000
50145
|
if (maskAllText) {
|
|
50001
50146
|
unmaskDistance = distanceToMatch(el, unmaskTextSelector);
|
|
50002
50147
|
if (unmaskDistance < 0) {
|
|
@@ -50029,8 +50174,8 @@ function isNumberInput(element) {
|
|
|
50029
50174
|
}
|
|
50030
50175
|
function shouldMaskInput(element, maskInputOptions) {
|
|
50031
50176
|
if (maskInputOptions && isElementNode(element)) {
|
|
50032
|
-
|
|
50033
|
-
|
|
50177
|
+
const tagName = (element.tagName || '').toLowerCase();
|
|
50178
|
+
const type = (element.type || '').toLowerCase();
|
|
50034
50179
|
if (maskInputOptions[tagName] || maskInputOptions[type]) {
|
|
50035
50180
|
return true;
|
|
50036
50181
|
}
|
|
@@ -51544,12 +51689,12 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51544
51689
|
}
|
|
51545
51690
|
}
|
|
51546
51691
|
|
|
51547
|
-
|
|
51692
|
+
const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
|
|
51548
51693
|
function matchHostedResources(recordingEvent, stringifiedRecordingPayload) {
|
|
51549
|
-
|
|
51550
|
-
|
|
51694
|
+
const fontURLRegex = /https:\/\/[^"\\\s]+?\.(woff2?|ttf|otf|eot)(\?[^"\\\s]*)?\b/g;
|
|
51695
|
+
const matches = stringifiedRecordingPayload.match(fontURLRegex);
|
|
51551
51696
|
// de-duplicate matches
|
|
51552
|
-
|
|
51697
|
+
const hostedResources = matches ? Array.from(new Set(matches)) : [];
|
|
51553
51698
|
return {
|
|
51554
51699
|
type: 'recording',
|
|
51555
51700
|
visitorId: recordingEvent.visitorId,
|
|
@@ -51564,7 +51709,7 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51564
51709
|
recordingPayloadMetadata: [],
|
|
51565
51710
|
sequence: 0,
|
|
51566
51711
|
recordingPayloadCount: 0,
|
|
51567
|
-
hostedResources
|
|
51712
|
+
hostedResources
|
|
51568
51713
|
};
|
|
51569
51714
|
}
|
|
51570
51715
|
// keep in mind changes here may need addressing in the extension worker proxy as well
|
|
@@ -51572,69 +51717,69 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
|
|
|
51572
51717
|
try {
|
|
51573
51718
|
if (e.data.type === 'init' && e.data.lockID) {
|
|
51574
51719
|
if (navigator.locks) {
|
|
51575
|
-
navigator.locks.request(e.data.lockID,
|
|
51720
|
+
navigator.locks.request(e.data.lockID, () => {
|
|
51576
51721
|
postMessage({ ready: true });
|
|
51577
51722
|
// This unresolved promise keeps the lock held with the worker until the worker is
|
|
51578
51723
|
// terminated at which point the lock is released.
|
|
51579
|
-
return new Promise$2(
|
|
51724
|
+
return new Promise$2(() => { });
|
|
51580
51725
|
});
|
|
51581
51726
|
}
|
|
51582
51727
|
return;
|
|
51583
51728
|
}
|
|
51584
51729
|
if (e.data.url && e.data.payload) {
|
|
51585
|
-
|
|
51730
|
+
let { url, payload, shouldCacheResources } = e.data;
|
|
51586
51731
|
if (Object.keys(payload).length === 0) {
|
|
51587
51732
|
postMessage({
|
|
51588
51733
|
type: 'emptyPayload'
|
|
51589
51734
|
});
|
|
51590
51735
|
}
|
|
51591
|
-
|
|
51592
|
-
|
|
51736
|
+
const { sequence } = payload;
|
|
51737
|
+
const stringifiedRecordingPayload = JSON.stringify(payload.recordingPayload);
|
|
51593
51738
|
// calculate and post back the recording payload size before the payload is compressed
|
|
51594
|
-
|
|
51595
|
-
|
|
51739
|
+
const recordingPayloadSize = new TextEncoder().encode(stringifiedRecordingPayload).length;
|
|
51740
|
+
const exceedsPayloadSizeLimit = recordingPayloadSize >= ONE_HUNDRED_MB_IN_BYTES;
|
|
51596
51741
|
postMessage({
|
|
51597
51742
|
type: 'recordingPayloadSize',
|
|
51598
|
-
recordingPayloadSize
|
|
51599
|
-
exceedsPayloadSizeLimit
|
|
51743
|
+
recordingPayloadSize,
|
|
51744
|
+
exceedsPayloadSizeLimit
|
|
51600
51745
|
});
|
|
51601
51746
|
// don't attempt to send the payload if it exceeds the allowed limit
|
|
51602
51747
|
if (exceedsPayloadSizeLimit)
|
|
51603
51748
|
return;
|
|
51604
51749
|
if (shouldCacheResources) {
|
|
51605
|
-
|
|
51750
|
+
const hostedResourcesEvent = matchHostedResources(payload, stringifiedRecordingPayload);
|
|
51606
51751
|
if (hostedResourcesEvent.hostedResources.length) {
|
|
51607
51752
|
postMessage({
|
|
51608
51753
|
type: 'hostedResources',
|
|
51609
|
-
hostedResourcesEvent
|
|
51754
|
+
hostedResourcesEvent
|
|
51610
51755
|
});
|
|
51611
51756
|
}
|
|
51612
51757
|
}
|
|
51613
51758
|
payload.recordingSize = recordingPayloadSize;
|
|
51614
|
-
|
|
51759
|
+
const body = compress(payload, 'binary');
|
|
51615
51760
|
// we want to calculate ct (current time) as close as we can to the actual POST request
|
|
51616
51761
|
// so that it's as accurate as possible
|
|
51617
|
-
url =
|
|
51762
|
+
url = `${url}&ct=${new Date().getTime()}`;
|
|
51618
51763
|
fetch(url, {
|
|
51619
51764
|
method: 'POST',
|
|
51620
|
-
body
|
|
51765
|
+
body
|
|
51621
51766
|
}).then(function (response) {
|
|
51622
51767
|
if (response.status < 200 || response.status >= 300) {
|
|
51623
51768
|
postMessage({
|
|
51624
|
-
error: new Error(
|
|
51769
|
+
error: new Error(`received status code ${response.status}: ${response.statusText}`),
|
|
51625
51770
|
status: response.status,
|
|
51626
|
-
sequence
|
|
51771
|
+
sequence
|
|
51627
51772
|
});
|
|
51628
51773
|
}
|
|
51629
51774
|
else {
|
|
51630
51775
|
postMessage({
|
|
51631
|
-
sequence
|
|
51776
|
+
sequence
|
|
51632
51777
|
});
|
|
51633
51778
|
}
|
|
51634
|
-
})
|
|
51779
|
+
}).catch(function (e) {
|
|
51635
51780
|
postMessage({
|
|
51636
51781
|
error: e,
|
|
51637
|
-
sequence
|
|
51782
|
+
sequence
|
|
51638
51783
|
});
|
|
51639
51784
|
});
|
|
51640
51785
|
}
|
|
@@ -51669,12 +51814,12 @@ function createReplayPlugin() {
|
|
|
51669
51814
|
* limit of number of keys in an object
|
|
51670
51815
|
* if an object contains more keys than this limit, we would call its toString function directly
|
|
51671
51816
|
*/
|
|
51672
|
-
|
|
51817
|
+
const NUM_OF_KEYS_LIMIT = 50;
|
|
51673
51818
|
/**
|
|
51674
51819
|
* limit number of depth in an object
|
|
51675
51820
|
* if an object is too deep, toString process may cause browser OOM
|
|
51676
51821
|
*/
|
|
51677
|
-
|
|
51822
|
+
const DEPTH_OF_LIMIT = 4;
|
|
51678
51823
|
/**
|
|
51679
51824
|
* serialize an HTML element by creating a shallow clone of it with text content
|
|
51680
51825
|
* and return the resulting outerHTML string (without the subtree)
|
|
@@ -51685,8 +51830,8 @@ function serializeHTML(node) {
|
|
|
51685
51830
|
if (!node || node.nodeType !== node.ELEMENT_NODE) {
|
|
51686
51831
|
return '';
|
|
51687
51832
|
}
|
|
51688
|
-
|
|
51689
|
-
|
|
51833
|
+
const nodeClone = node.cloneNode(false);
|
|
51834
|
+
const { textContent } = node;
|
|
51690
51835
|
if (textContent) {
|
|
51691
51836
|
nodeClone.textContent = textContent;
|
|
51692
51837
|
}
|
|
@@ -51700,7 +51845,7 @@ function isObject(obj) {
|
|
|
51700
51845
|
return false;
|
|
51701
51846
|
if (typeof obj !== 'object')
|
|
51702
51847
|
return false;
|
|
51703
|
-
|
|
51848
|
+
const proto = Object.getPrototypeOf(obj);
|
|
51704
51849
|
return proto === Object.prototype || proto === null;
|
|
51705
51850
|
}
|
|
51706
51851
|
/**
|
|
@@ -51709,11 +51854,11 @@ function isObject(obj) {
|
|
|
51709
51854
|
function isObjTooDeep(obj, limit) {
|
|
51710
51855
|
if (limit === 0)
|
|
51711
51856
|
return true;
|
|
51712
|
-
|
|
51857
|
+
const keys = Object.keys(obj);
|
|
51713
51858
|
if (keys.length === 0)
|
|
51714
51859
|
return false;
|
|
51715
|
-
return keys.some(
|
|
51716
|
-
|
|
51860
|
+
return keys.some(key => {
|
|
51861
|
+
const value = obj[key];
|
|
51717
51862
|
return isObject(value) && isObjTooDeep(value, limit - 1);
|
|
51718
51863
|
});
|
|
51719
51864
|
}
|
|
@@ -51729,7 +51874,7 @@ function shouldIgnore(_obj) {
|
|
|
51729
51874
|
return false;
|
|
51730
51875
|
}
|
|
51731
51876
|
// out of keys limit
|
|
51732
|
-
|
|
51877
|
+
const keys = Object.keys(_obj);
|
|
51733
51878
|
if (keys.length > NUM_OF_KEYS_LIMIT) {
|
|
51734
51879
|
return true;
|
|
51735
51880
|
}
|
|
@@ -51761,7 +51906,7 @@ function stringify(arg) {
|
|
|
51761
51906
|
return value.toString ? value.toString() : '[object Object]';
|
|
51762
51907
|
}
|
|
51763
51908
|
if (value instanceof ArrayBuffer)
|
|
51764
|
-
return
|
|
51909
|
+
return `ArrayBuffer { byteLength: ${value.byteLength} }`;
|
|
51765
51910
|
if (value instanceof Error)
|
|
51766
51911
|
return value.name + ': ' + value.message;
|
|
51767
51912
|
if (value instanceof Node) {
|
|
@@ -51769,10 +51914,10 @@ function stringify(arg) {
|
|
|
51769
51914
|
}
|
|
51770
51915
|
// Handle events
|
|
51771
51916
|
if (value instanceof Event) {
|
|
51772
|
-
|
|
51917
|
+
const eventResult = {};
|
|
51773
51918
|
// eslint-disable-next-line guard-for-in
|
|
51774
|
-
for (
|
|
51775
|
-
|
|
51919
|
+
for (const eventKey in value) {
|
|
51920
|
+
const eventValue = value[eventKey];
|
|
51776
51921
|
eventResult[eventKey] = Array.isArray(eventValue) && eventValue[0] instanceof HTMLElement
|
|
51777
51922
|
? serializeHTML(eventValue[0])
|
|
51778
51923
|
: eventValue;
|
|
@@ -51783,31 +51928,30 @@ function stringify(arg) {
|
|
|
51783
51928
|
});
|
|
51784
51929
|
}
|
|
51785
51930
|
|
|
51786
|
-
|
|
51787
|
-
|
|
51931
|
+
class StackFrame {
|
|
51932
|
+
constructor(obj) {
|
|
51788
51933
|
this.fileName = obj.fileName || '';
|
|
51789
51934
|
this.functionName = obj.functionName || '';
|
|
51790
51935
|
this.lineNumber = obj.lineNumber;
|
|
51791
51936
|
this.columnNumber = obj.columnNumber;
|
|
51792
51937
|
}
|
|
51793
|
-
|
|
51794
|
-
|
|
51938
|
+
toString() {
|
|
51939
|
+
const { fileName, functionName, lineNumber = '', columnNumber = '' } = this;
|
|
51795
51940
|
return functionName
|
|
51796
|
-
?
|
|
51797
|
-
:
|
|
51798
|
-
}
|
|
51799
|
-
|
|
51800
|
-
|
|
51801
|
-
|
|
51802
|
-
|
|
51803
|
-
|
|
51804
|
-
|
|
51805
|
-
|
|
51806
|
-
var ErrorStackParser = {
|
|
51941
|
+
? `${functionName} (${fileName}:${lineNumber}:${columnNumber})`
|
|
51942
|
+
: `${fileName}:${lineNumber}:${columnNumber}`;
|
|
51943
|
+
}
|
|
51944
|
+
}
|
|
51945
|
+
const FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
|
|
51946
|
+
const CHROME_EDGE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m;
|
|
51947
|
+
const SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/;
|
|
51948
|
+
const LOCATION_REGEXP = /(.+?)(?::(\d+))?(?::(\d+))?$/;
|
|
51949
|
+
const DEFAULT_NUM_FRAMES_TO_SKIP = 5;
|
|
51950
|
+
const ErrorStackParser = {
|
|
51807
51951
|
/**
|
|
51808
51952
|
* Given an Error object, extract the most information from it.
|
|
51809
51953
|
*/
|
|
51810
|
-
parse
|
|
51954
|
+
parse(error, maxFramesToSave) {
|
|
51811
51955
|
if (!(error === null || error === void 0 ? void 0 : error.stack))
|
|
51812
51956
|
return [];
|
|
51813
51957
|
// Chrome, Edge, Opera ≥15
|
|
@@ -51821,25 +51965,24 @@ var ErrorStackParser = {
|
|
|
51821
51965
|
return [];
|
|
51822
51966
|
},
|
|
51823
51967
|
// Separate line and column numbers from a string of the form: (URI:Line:Column)
|
|
51824
|
-
extractLocation
|
|
51968
|
+
extractLocation(urlLike) {
|
|
51825
51969
|
// Fail-fast but return locations like "(native)"
|
|
51826
51970
|
if (urlLike.indexOf(':') === -1) {
|
|
51827
51971
|
return [urlLike];
|
|
51828
51972
|
}
|
|
51829
|
-
|
|
51973
|
+
const parts = LOCATION_REGEXP.exec(urlLike.replace(/[()]/g, ''));
|
|
51830
51974
|
if (!parts)
|
|
51831
|
-
throw new Error(
|
|
51975
|
+
throw new Error(`Cannot parse given url: ${urlLike}`);
|
|
51832
51976
|
return [parts[1], parts[2] || undefined, parts[3] || undefined];
|
|
51833
51977
|
},
|
|
51834
|
-
parseHelper
|
|
51835
|
-
|
|
51836
|
-
|
|
51837
|
-
|
|
51838
|
-
|
|
51839
|
-
|
|
51840
|
-
|
|
51841
|
-
|
|
51842
|
-
var shouldSkipLine = (includeMatchedLine && !lineMatchesRegex) || // if line doesn't match regex and we want matched lines, skip it
|
|
51978
|
+
parseHelper({ regex, includeMatchedLine }, error, maxFramesToSave, callback) {
|
|
51979
|
+
const lines = error.stack.split('\n');
|
|
51980
|
+
const frames = [];
|
|
51981
|
+
let validFramesFound = 0;
|
|
51982
|
+
for (let i = 0; i < lines.length; i++) {
|
|
51983
|
+
const line = lines[i];
|
|
51984
|
+
const lineMatchesRegex = regex.test(line);
|
|
51985
|
+
const shouldSkipLine = (includeMatchedLine && !lineMatchesRegex) || // if line doesn't match regex and we want matched lines, skip it
|
|
51843
51986
|
(!includeMatchedLine && lineMatchesRegex); // if line does match regex but we don't want matched lines, skip it
|
|
51844
51987
|
if (shouldSkipLine)
|
|
51845
51988
|
continue;
|
|
@@ -51854,12 +51997,11 @@ var ErrorStackParser = {
|
|
|
51854
51997
|
}
|
|
51855
51998
|
return frames;
|
|
51856
51999
|
},
|
|
51857
|
-
parseChromiumStack
|
|
51858
|
-
|
|
51859
|
-
|
|
51860
|
-
var sanitizedLine;
|
|
52000
|
+
parseChromiumStack(error, maxFramesToSave) {
|
|
52001
|
+
return this.parseHelper({ regex: CHROME_EDGE_STACK_REGEXP, includeMatchedLine: true }, error, maxFramesToSave, (line, frames) => {
|
|
52002
|
+
let sanitizedLine;
|
|
51861
52003
|
if (line.indexOf('(eval ') > -1) {
|
|
51862
|
-
|
|
52004
|
+
const processedLine = line
|
|
51863
52005
|
.replace(/eval code/g, 'eval')
|
|
51864
52006
|
.replace(/(\(eval at [^()]*)|(\),.*$)/g, '');
|
|
51865
52007
|
sanitizedLine = processedLine.replace(/^\s+/, '').replace(/\(eval code/g, '(');
|
|
@@ -51869,7 +52011,7 @@ var ErrorStackParser = {
|
|
|
51869
52011
|
}
|
|
51870
52012
|
// capture and preserve the parenthesized location "(/foo/my bar.js:12:87)"
|
|
51871
52013
|
// in case it has spaces in it, as the string is split on \s+ later on
|
|
51872
|
-
|
|
52014
|
+
let location;
|
|
51873
52015
|
if (sanitizedLine.indexOf('(') > -1 && sanitizedLine.indexOf('):') > -1) {
|
|
51874
52016
|
location = sanitizedLine.match(/ (\((.+):(\d+):(\d+)\)$)/);
|
|
51875
52017
|
}
|
|
@@ -51877,23 +52019,22 @@ var ErrorStackParser = {
|
|
|
51877
52019
|
sanitizedLine = location
|
|
51878
52020
|
? sanitizedLine.replace(location[0], '')
|
|
51879
52021
|
: sanitizedLine;
|
|
51880
|
-
|
|
52022
|
+
const tokens = sanitizedLine.split(/\s+/).slice(1);
|
|
51881
52023
|
// if a location was matched, pass it to extractLocation() otherwise pop the last token
|
|
51882
|
-
|
|
51883
|
-
|
|
51884
|
-
|
|
52024
|
+
const locationParts = this.extractLocation(location ? location[1] : tokens.pop() || '');
|
|
52025
|
+
const functionName = tokens.join(' ') || undefined;
|
|
52026
|
+
const fileName = (locationParts[0] === 'eval' || locationParts[0] === '<anonymous>') ? undefined : locationParts[0];
|
|
51885
52027
|
frames.push(new StackFrame({
|
|
51886
|
-
functionName
|
|
51887
|
-
fileName
|
|
52028
|
+
functionName,
|
|
52029
|
+
fileName,
|
|
51888
52030
|
lineNumber: locationParts[1],
|
|
51889
52031
|
columnNumber: locationParts[2]
|
|
51890
52032
|
}));
|
|
51891
52033
|
});
|
|
51892
52034
|
},
|
|
51893
|
-
parseFirefoxSafariStack
|
|
51894
|
-
|
|
51895
|
-
|
|
51896
|
-
var processedLine = line;
|
|
52035
|
+
parseFirefoxSafariStack(error, maxFramesToSave) {
|
|
52036
|
+
return this.parseHelper({ regex: SAFARI_NATIVE_CODE_REGEXP, includeMatchedLine: false }, error, maxFramesToSave, (line, frames) => {
|
|
52037
|
+
let processedLine = line;
|
|
51897
52038
|
// Throw away eval information until we implement stacktrace.js/stackframe#8
|
|
51898
52039
|
if (processedLine.indexOf(' > eval') > -1) {
|
|
51899
52040
|
processedLine = processedLine.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ':$1');
|
|
@@ -51905,12 +52046,12 @@ var ErrorStackParser = {
|
|
|
51905
52046
|
}));
|
|
51906
52047
|
return;
|
|
51907
52048
|
}
|
|
51908
|
-
|
|
51909
|
-
|
|
51910
|
-
|
|
51911
|
-
|
|
52049
|
+
const functionNameRegex = /((.*".+"[^@]*)?[^@]*)(?:@)/;
|
|
52050
|
+
const matches = processedLine.match(functionNameRegex);
|
|
52051
|
+
const functionName = matches && matches[1] ? matches[1] : undefined;
|
|
52052
|
+
const locationParts = this.extractLocation(processedLine.replace(functionNameRegex, ''));
|
|
51912
52053
|
frames.push(new StackFrame({
|
|
51913
|
-
functionName
|
|
52054
|
+
functionName,
|
|
51914
52055
|
fileName: locationParts[0],
|
|
51915
52056
|
lineNumber: locationParts[1],
|
|
51916
52057
|
columnNumber: locationParts[2]
|
|
@@ -51945,7 +52086,7 @@ function includes(str, substring) {
|
|
|
51945
52086
|
function getResourceType(blockedURI, directive) {
|
|
51946
52087
|
if (!directive || typeof directive !== 'string')
|
|
51947
52088
|
return 'resource';
|
|
51948
|
-
|
|
52089
|
+
const d = directive.toLowerCase();
|
|
51949
52090
|
if (blockedURI === 'inline') {
|
|
51950
52091
|
if (includes(d, 'script-src-attr')) {
|
|
51951
52092
|
return 'inline event handler';
|
|
@@ -52004,12 +52145,11 @@ function getResourceType(blockedURI, directive) {
|
|
|
52004
52145
|
function getDirective(policy, directiveName) {
|
|
52005
52146
|
if (!policy || !directiveName)
|
|
52006
52147
|
return '';
|
|
52007
|
-
|
|
52008
|
-
for (
|
|
52009
|
-
|
|
52010
|
-
|
|
52011
|
-
|
|
52012
|
-
if (lower === needle || lower.startsWith("".concat(needle, " "))) {
|
|
52148
|
+
const needle = directiveName.toLowerCase();
|
|
52149
|
+
for (const directive of policy.split(';')) {
|
|
52150
|
+
const trimmed = directive.trim();
|
|
52151
|
+
const lower = trimmed.toLowerCase();
|
|
52152
|
+
if (lower === needle || lower.startsWith(`${needle} `)) {
|
|
52013
52153
|
return trimmed;
|
|
52014
52154
|
}
|
|
52015
52155
|
}
|
|
@@ -52031,7 +52171,7 @@ function getDirective(policy, directiveName) {
|
|
|
52031
52171
|
function getArticle(phrase) {
|
|
52032
52172
|
if (!phrase || typeof phrase !== 'string')
|
|
52033
52173
|
return 'A';
|
|
52034
|
-
|
|
52174
|
+
const c = phrase.trim().charAt(0).toLowerCase();
|
|
52035
52175
|
return includes('aeiou', c) ? 'An' : 'A';
|
|
52036
52176
|
}
|
|
52037
52177
|
/**
|
|
@@ -52074,47 +52214,46 @@ function createCspViolationMessage(blockedURI, directive, isReportOnly, original
|
|
|
52074
52214
|
return 'Content Security Policy: Unknown violation occurred.';
|
|
52075
52215
|
}
|
|
52076
52216
|
try {
|
|
52077
|
-
|
|
52217
|
+
const reportOnlyText = isReportOnly ? ' (Report-Only)' : '';
|
|
52078
52218
|
// special case for frame-ancestors since it doesn't fit our template at all
|
|
52079
52219
|
if ((directive === null || directive === void 0 ? void 0 : directive.toLowerCase()) === 'frame-ancestors') {
|
|
52080
|
-
return
|
|
52220
|
+
return `Content Security Policy${reportOnlyText}: The display of ${blockedURI} in a frame was blocked because an ancestor violates your site's frame-ancestors policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
52081
52221
|
}
|
|
52082
|
-
|
|
52083
|
-
|
|
52084
|
-
|
|
52085
|
-
|
|
52086
|
-
|
|
52087
|
-
|
|
52088
|
-
return
|
|
52222
|
+
const resourceType = getResourceType(blockedURI, directive);
|
|
52223
|
+
const article = getArticle(resourceType);
|
|
52224
|
+
const source = formatBlockedUri(blockedURI);
|
|
52225
|
+
const directiveValue = getDirective(originalPolicy, directive);
|
|
52226
|
+
const policyDisplay = directiveValue || directive;
|
|
52227
|
+
const resourceDescription = `${article} ${resourceType}${source ? ` from ${source}` : ''}`;
|
|
52228
|
+
return `Content Security Policy${reportOnlyText}: ${resourceDescription} was blocked by your site's \`${policyDisplay}\` policy.\nCurrent CSP: "${originalPolicy}".`;
|
|
52089
52229
|
}
|
|
52090
52230
|
catch (error) {
|
|
52091
|
-
return
|
|
52231
|
+
return `Content Security Policy: Error formatting violation message: ${error.message}`;
|
|
52092
52232
|
}
|
|
52093
52233
|
}
|
|
52094
52234
|
|
|
52095
|
-
|
|
52096
|
-
|
|
52235
|
+
const MAX_LENGTH = 1000;
|
|
52236
|
+
const PII_PATTERN = {
|
|
52097
52237
|
ip: /\b(?:\d{1,3}\.){3}\d{1,3}\b/g,
|
|
52098
52238
|
ssn: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
52099
52239
|
creditCard: /\b(?:\d[ -]?){12,18}\d\b/g,
|
|
52100
52240
|
httpsUrls: /https:\/\/[^\s]+/g,
|
|
52101
52241
|
email: /[\w._+-]+@[\w.-]+\.\w+/g
|
|
52102
52242
|
};
|
|
52103
|
-
|
|
52104
|
-
|
|
52105
|
-
|
|
52106
|
-
|
|
52107
|
-
|
|
52243
|
+
const PII_REPLACEMENT = '*'.repeat(10);
|
|
52244
|
+
const JSON_PII_KEYS = ['password', 'email', 'key', 'token', 'auth', 'authentication', 'phone', 'address', 'ssn'];
|
|
52245
|
+
const UNABLE_TO_DISPLAY_BODY = '[Unable to display body: detected PII could not be redacted]';
|
|
52246
|
+
const joinedKeys = JSON_PII_KEYS.join('|');
|
|
52247
|
+
const keyPattern = `"([^"]*(?:${joinedKeys})[^"]*)"`;
|
|
52108
52248
|
// only scrub strings, numbers, and booleans
|
|
52109
|
-
|
|
52249
|
+
const acceptedValues = '("([^"\\\\]*(?:\\\\.[^"\\\\]*)*")|(\\d+)|(true|false))';
|
|
52110
52250
|
/**
|
|
52111
52251
|
* Truncates a string to the max length
|
|
52112
52252
|
* @access private
|
|
52113
52253
|
* @param {String} string
|
|
52114
52254
|
* @returns {String}
|
|
52115
52255
|
*/
|
|
52116
|
-
function truncate(string, includeEllipsis) {
|
|
52117
|
-
if (includeEllipsis === void 0) { includeEllipsis = false; }
|
|
52256
|
+
function truncate(string, includeEllipsis = false) {
|
|
52118
52257
|
if (string.length <= MAX_LENGTH)
|
|
52119
52258
|
return string;
|
|
52120
52259
|
if (includeEllipsis) {
|
|
@@ -52131,7 +52270,7 @@ function truncate(string, includeEllipsis) {
|
|
|
52131
52270
|
* @returns {String}
|
|
52132
52271
|
*/
|
|
52133
52272
|
function generateLogKey(methodName, message, stackTrace) {
|
|
52134
|
-
return
|
|
52273
|
+
return `${methodName}|${message}|${stackTrace}`;
|
|
52135
52274
|
}
|
|
52136
52275
|
/**
|
|
52137
52276
|
* Checks if a string has 2 or more digits, a https URL, or an email address
|
|
@@ -52148,13 +52287,12 @@ function mightContainPII(string) {
|
|
|
52148
52287
|
* @param {String} string
|
|
52149
52288
|
* @returns {String}
|
|
52150
52289
|
*/
|
|
52151
|
-
function scrubPII(
|
|
52152
|
-
var string = _a.string, _ = _a._;
|
|
52290
|
+
function scrubPII({ string, _ }) {
|
|
52153
52291
|
if (!string || typeof string !== 'string')
|
|
52154
52292
|
return string;
|
|
52155
52293
|
if (!mightContainPII(string))
|
|
52156
52294
|
return string;
|
|
52157
|
-
return _.reduce(_.values(PII_PATTERN),
|
|
52295
|
+
return _.reduce(_.values(PII_PATTERN), (str, pattern) => str.replace(pattern, PII_REPLACEMENT), string);
|
|
52158
52296
|
}
|
|
52159
52297
|
/**
|
|
52160
52298
|
* Scrub PII from a stringified JSON object
|
|
@@ -52163,14 +52301,12 @@ function scrubPII(_a) {
|
|
|
52163
52301
|
* @returns {String}
|
|
52164
52302
|
*/
|
|
52165
52303
|
function scrubJsonPII(string) {
|
|
52166
|
-
|
|
52304
|
+
const fullScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*[\\{\\[]`, 'i');
|
|
52167
52305
|
if (fullScrubRegex.test(string)) {
|
|
52168
52306
|
return UNABLE_TO_DISPLAY_BODY;
|
|
52169
52307
|
}
|
|
52170
|
-
|
|
52171
|
-
return string.replace(keyValueScrubRegex,
|
|
52172
|
-
return "\"".concat(key, "\":\"").concat(PII_REPLACEMENT, "\"");
|
|
52173
|
-
});
|
|
52308
|
+
const keyValueScrubRegex = new RegExp(`${keyPattern}\\s*:\\s*${acceptedValues}`, 'gi');
|
|
52309
|
+
return string.replace(keyValueScrubRegex, (match, key) => `"${key}":"${PII_REPLACEMENT}"`);
|
|
52174
52310
|
}
|
|
52175
52311
|
/**
|
|
52176
52312
|
* Checks if a string is a JSON object
|
|
@@ -52182,7 +52318,7 @@ function scrubJsonPII(string) {
|
|
|
52182
52318
|
function mightContainJson(string, contentType) {
|
|
52183
52319
|
if (!string || typeof string !== 'string')
|
|
52184
52320
|
return false;
|
|
52185
|
-
|
|
52321
|
+
const firstChar = string.charAt(0);
|
|
52186
52322
|
if (contentType && contentType.indexOf('application/json') !== -1) {
|
|
52187
52323
|
return true;
|
|
52188
52324
|
}
|
|
@@ -52195,20 +52331,19 @@ function mightContainJson(string, contentType) {
|
|
|
52195
52331
|
* @param {String} contentType
|
|
52196
52332
|
* @returns {String}
|
|
52197
52333
|
*/
|
|
52198
|
-
function maskSensitiveFields(
|
|
52199
|
-
var string = _a.string, contentType = _a.contentType, _ = _a._;
|
|
52334
|
+
function maskSensitiveFields({ string, contentType, _ }) {
|
|
52200
52335
|
if (!string || typeof string !== 'string')
|
|
52201
52336
|
return string;
|
|
52202
52337
|
if (mightContainJson(string, contentType)) {
|
|
52203
52338
|
string = scrubJsonPII(string);
|
|
52204
52339
|
}
|
|
52205
52340
|
if (mightContainPII(string)) {
|
|
52206
|
-
string = scrubPII({ string
|
|
52341
|
+
string = scrubPII({ string, _ });
|
|
52207
52342
|
}
|
|
52208
52343
|
return string;
|
|
52209
52344
|
}
|
|
52210
52345
|
|
|
52211
|
-
|
|
52346
|
+
const DEV_LOG_TYPE = 'devlog';
|
|
52212
52347
|
function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
52213
52348
|
return {
|
|
52214
52349
|
browser_time: pluginAPI.util.getNow(),
|
|
@@ -52219,12 +52354,12 @@ function createDevLogEnvelope(pluginAPI, globalPendo) {
|
|
|
52219
52354
|
};
|
|
52220
52355
|
}
|
|
52221
52356
|
|
|
52222
|
-
|
|
52223
|
-
|
|
52224
|
-
|
|
52225
|
-
|
|
52226
|
-
|
|
52227
|
-
|
|
52357
|
+
const TOKEN_MAX_SIZE = 100;
|
|
52358
|
+
const TOKEN_REFILL_RATE = 10;
|
|
52359
|
+
const TOKEN_REFRESH_INTERVAL = 1000;
|
|
52360
|
+
const MAX_UNCOMPRESSED_SIZE = 125000; // 125KB
|
|
52361
|
+
class DevlogBuffer {
|
|
52362
|
+
constructor(pendo, pluginAPI) {
|
|
52228
52363
|
this.pendo = pendo;
|
|
52229
52364
|
this.pluginAPI = pluginAPI;
|
|
52230
52365
|
this.events = [];
|
|
@@ -52235,36 +52370,36 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
52235
52370
|
this.lastRefillTime = this.pluginAPI.util.getNow();
|
|
52236
52371
|
this.nextRefillTime = this.lastRefillTime + TOKEN_REFRESH_INTERVAL;
|
|
52237
52372
|
}
|
|
52238
|
-
|
|
52373
|
+
isEmpty() {
|
|
52239
52374
|
return this.events.length === 0 && this.payloads.length === 0;
|
|
52240
|
-
}
|
|
52241
|
-
|
|
52242
|
-
|
|
52375
|
+
}
|
|
52376
|
+
refillTokens() {
|
|
52377
|
+
const now = this.pluginAPI.util.getNow();
|
|
52243
52378
|
if (now >= this.nextRefillTime) {
|
|
52244
|
-
|
|
52245
|
-
|
|
52246
|
-
|
|
52379
|
+
const timeSinceLastRefill = now - this.lastRefillTime;
|
|
52380
|
+
const secondsSinceLastRefill = Math.floor(timeSinceLastRefill / TOKEN_REFRESH_INTERVAL);
|
|
52381
|
+
const tokensToRefill = secondsSinceLastRefill * TOKEN_REFILL_RATE;
|
|
52247
52382
|
this.tokens = Math.min(this.tokens + tokensToRefill, TOKEN_MAX_SIZE);
|
|
52248
52383
|
this.lastRefillTime = now;
|
|
52249
52384
|
this.nextRefillTime = now + TOKEN_REFRESH_INTERVAL;
|
|
52250
52385
|
}
|
|
52251
|
-
}
|
|
52252
|
-
|
|
52386
|
+
}
|
|
52387
|
+
clear() {
|
|
52253
52388
|
this.events = [];
|
|
52254
52389
|
this.lastEvent = null;
|
|
52255
52390
|
this.uncompressedSize = 0;
|
|
52256
|
-
}
|
|
52257
|
-
|
|
52391
|
+
}
|
|
52392
|
+
hasTokenAvailable() {
|
|
52258
52393
|
this.refillTokens();
|
|
52259
52394
|
return this.tokens > 0;
|
|
52260
|
-
}
|
|
52261
|
-
|
|
52395
|
+
}
|
|
52396
|
+
estimateEventSize(event) {
|
|
52262
52397
|
return JSON.stringify(event).length;
|
|
52263
|
-
}
|
|
52264
|
-
|
|
52398
|
+
}
|
|
52399
|
+
push(event) {
|
|
52265
52400
|
if (!this.hasTokenAvailable())
|
|
52266
52401
|
return false;
|
|
52267
|
-
|
|
52402
|
+
const eventSize = this.estimateEventSize(event);
|
|
52268
52403
|
if (this.uncompressedSize + eventSize > MAX_UNCOMPRESSED_SIZE) {
|
|
52269
52404
|
this.compressCurrentChunk();
|
|
52270
52405
|
}
|
|
@@ -52273,55 +52408,54 @@ var DevlogBuffer = /** @class */ (function () {
|
|
|
52273
52408
|
this.events.push(event);
|
|
52274
52409
|
this.tokens = Math.max(this.tokens - 1, 0);
|
|
52275
52410
|
return true;
|
|
52276
|
-
}
|
|
52277
|
-
|
|
52411
|
+
}
|
|
52412
|
+
compressCurrentChunk() {
|
|
52278
52413
|
if (this.events.length === 0)
|
|
52279
52414
|
return;
|
|
52280
|
-
|
|
52415
|
+
const jzb = this.pendo.compress(this.events);
|
|
52281
52416
|
this.payloads.push(jzb);
|
|
52282
52417
|
this.clear();
|
|
52283
|
-
}
|
|
52284
|
-
|
|
52285
|
-
|
|
52418
|
+
}
|
|
52419
|
+
generateUrl() {
|
|
52420
|
+
const queryParams = {
|
|
52286
52421
|
v: this.pendo.VERSION,
|
|
52287
52422
|
ct: this.pluginAPI.util.getNow()
|
|
52288
52423
|
};
|
|
52289
52424
|
return this.pluginAPI.transmit.buildBaseDataUrl(DEV_LOG_TYPE, this.pendo.apiKey, queryParams);
|
|
52290
|
-
}
|
|
52291
|
-
|
|
52425
|
+
}
|
|
52426
|
+
pack() {
|
|
52292
52427
|
if (this.isEmpty())
|
|
52293
52428
|
return;
|
|
52294
|
-
|
|
52429
|
+
const url = this.generateUrl();
|
|
52295
52430
|
this.compressCurrentChunk();
|
|
52296
|
-
|
|
52297
|
-
jzb
|
|
52298
|
-
url
|
|
52299
|
-
})
|
|
52431
|
+
const payloads = this.pendo._.map(this.payloads, (jzb) => ({
|
|
52432
|
+
jzb,
|
|
52433
|
+
url
|
|
52434
|
+
}));
|
|
52300
52435
|
this.payloads = [];
|
|
52301
52436
|
return payloads;
|
|
52302
|
-
}
|
|
52303
|
-
|
|
52304
|
-
}());
|
|
52437
|
+
}
|
|
52438
|
+
}
|
|
52305
52439
|
|
|
52306
|
-
|
|
52307
|
-
|
|
52440
|
+
class DevlogTransport {
|
|
52441
|
+
constructor(globalPendo, pluginAPI) {
|
|
52308
52442
|
this.pendo = globalPendo;
|
|
52309
52443
|
this.pluginAPI = pluginAPI;
|
|
52310
52444
|
}
|
|
52311
|
-
|
|
52312
|
-
|
|
52445
|
+
buildGetUrl(baseUrl, jzb) {
|
|
52446
|
+
const params = {};
|
|
52313
52447
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
52314
52448
|
this.pluginAPI.agent.addAccountIdParams(params, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
52315
52449
|
}
|
|
52316
|
-
|
|
52450
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52317
52451
|
if (!this.pendo._.isEmpty(jwtOptions)) {
|
|
52318
52452
|
this.pendo._.extend(params, jwtOptions);
|
|
52319
52453
|
}
|
|
52320
52454
|
params.jzb = jzb;
|
|
52321
|
-
|
|
52322
|
-
return
|
|
52323
|
-
}
|
|
52324
|
-
|
|
52455
|
+
const queryString = this.pendo._.map(params, (value, key) => `${key}=${value}`).join('&');
|
|
52456
|
+
return `${baseUrl}${baseUrl.indexOf('?') !== -1 ? '&' : '?'}${queryString}`;
|
|
52457
|
+
}
|
|
52458
|
+
get(url, options) {
|
|
52325
52459
|
options.method = 'GET';
|
|
52326
52460
|
if (this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
52327
52461
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
@@ -52329,90 +52463,86 @@ var DevlogTransport = /** @class */ (function () {
|
|
|
52329
52463
|
else {
|
|
52330
52464
|
return this.pendo.ajax.get(url);
|
|
52331
52465
|
}
|
|
52332
|
-
}
|
|
52333
|
-
|
|
52334
|
-
|
|
52335
|
-
var getUrl = this.buildGetUrl(url, jzb);
|
|
52466
|
+
}
|
|
52467
|
+
sendRequestWithGet({ url, jzb }) {
|
|
52468
|
+
const getUrl = this.buildGetUrl(url, jzb);
|
|
52336
52469
|
return this.get(getUrl, {
|
|
52337
52470
|
headers: {
|
|
52338
52471
|
'Content-Type': 'application/octet-stream'
|
|
52339
52472
|
}
|
|
52340
52473
|
});
|
|
52341
|
-
}
|
|
52342
|
-
|
|
52474
|
+
}
|
|
52475
|
+
post(url, options) {
|
|
52343
52476
|
options.method = 'POST';
|
|
52344
52477
|
if (options.keepalive && this.pluginAPI.transmit.fetchKeepalive.supported()) {
|
|
52345
52478
|
return this.pluginAPI.transmit.fetchKeepalive(url, options);
|
|
52346
52479
|
}
|
|
52347
52480
|
else if (options.keepalive && this.pluginAPI.transmit.sendBeacon.supported()) {
|
|
52348
|
-
|
|
52481
|
+
const result = this.pluginAPI.transmit.sendBeacon(url, new Blob([options.body]));
|
|
52349
52482
|
return result ? Promise$2.resolve() : Promise$2.reject(new Error('sendBeacon failed to send devlog data'));
|
|
52350
52483
|
}
|
|
52351
52484
|
else {
|
|
52352
52485
|
return this.pendo.ajax.post(url, options.body);
|
|
52353
52486
|
}
|
|
52354
|
-
}
|
|
52355
|
-
|
|
52356
|
-
|
|
52357
|
-
|
|
52358
|
-
var bodyPayload = {
|
|
52487
|
+
}
|
|
52488
|
+
sendRequestWithPost({ url, jzb }, isUnload) {
|
|
52489
|
+
const jwtOptions = this.pluginAPI.agent.getJwtInfoCopy();
|
|
52490
|
+
const bodyPayload = {
|
|
52359
52491
|
events: jzb,
|
|
52360
52492
|
browser_time: this.pluginAPI.util.getNow()
|
|
52361
52493
|
};
|
|
52362
52494
|
if (this.pluginAPI.agent.treatAsAdoptPartner()) {
|
|
52363
52495
|
this.pluginAPI.agent.addAccountIdParams(bodyPayload, this.pendo.get_account_id(), this.pluginAPI.ConfigReader.get('oemAccountId'));
|
|
52364
52496
|
}
|
|
52365
|
-
|
|
52497
|
+
const body = JSON.stringify(this.pendo._.extend(bodyPayload, jwtOptions));
|
|
52366
52498
|
return this.post(url, {
|
|
52367
|
-
body
|
|
52499
|
+
body,
|
|
52368
52500
|
headers: {
|
|
52369
52501
|
'Content-Type': 'application/json'
|
|
52370
52502
|
},
|
|
52371
52503
|
keepalive: isUnload
|
|
52372
52504
|
});
|
|
52373
|
-
}
|
|
52374
|
-
|
|
52375
|
-
|
|
52376
|
-
var compressedLength = jzb.length;
|
|
52505
|
+
}
|
|
52506
|
+
sendRequest({ url, jzb }, isUnload) {
|
|
52507
|
+
const compressedLength = jzb.length;
|
|
52377
52508
|
if (compressedLength <= this.pluginAPI.constants.ENCODED_EVENT_MAX_LENGTH && !this.pluginAPI.ConfigReader.get('sendEventsWithPostOnly')) {
|
|
52378
|
-
return this.sendRequestWithGet({ url
|
|
52509
|
+
return this.sendRequestWithGet({ url, jzb });
|
|
52379
52510
|
}
|
|
52380
|
-
return this.sendRequestWithPost({ url
|
|
52381
|
-
}
|
|
52382
|
-
|
|
52383
|
-
}());
|
|
52511
|
+
return this.sendRequestWithPost({ url, jzb }, isUnload);
|
|
52512
|
+
}
|
|
52513
|
+
}
|
|
52384
52514
|
|
|
52385
52515
|
function ConsoleCapture() {
|
|
52386
|
-
|
|
52387
|
-
|
|
52388
|
-
|
|
52389
|
-
|
|
52390
|
-
|
|
52391
|
-
|
|
52392
|
-
|
|
52393
|
-
|
|
52394
|
-
|
|
52395
|
-
|
|
52396
|
-
|
|
52397
|
-
|
|
52516
|
+
let pluginAPI;
|
|
52517
|
+
let _;
|
|
52518
|
+
let globalPendo;
|
|
52519
|
+
let buffer;
|
|
52520
|
+
let sendQueue;
|
|
52521
|
+
let sendInterval;
|
|
52522
|
+
let transport;
|
|
52523
|
+
let isPtmPaused;
|
|
52524
|
+
let isCapturingConsoleLogs = false;
|
|
52525
|
+
const CAPTURE_CONSOLE_CONFIG = 'captureConsoleLogs';
|
|
52526
|
+
const CONSOLE_METHODS = ['log', 'warn', 'error', 'info'];
|
|
52527
|
+
const DEV_LOG_SUB_TYPE = 'console';
|
|
52398
52528
|
// deduplicate logs
|
|
52399
|
-
|
|
52529
|
+
let lastLogKey = '';
|
|
52400
52530
|
return {
|
|
52401
52531
|
name: 'ConsoleCapture',
|
|
52402
|
-
initialize
|
|
52403
|
-
teardown
|
|
52404
|
-
addIntercepts
|
|
52405
|
-
createConsoleEvent
|
|
52406
|
-
captureStackTrace
|
|
52407
|
-
send
|
|
52408
|
-
setCaptureState
|
|
52409
|
-
recordingStarted
|
|
52410
|
-
recordingStopped
|
|
52411
|
-
onAppHidden
|
|
52412
|
-
onAppUnloaded
|
|
52413
|
-
onPtmPaused
|
|
52414
|
-
onPtmUnpaused
|
|
52415
|
-
securityPolicyViolationFn
|
|
52532
|
+
initialize,
|
|
52533
|
+
teardown,
|
|
52534
|
+
addIntercepts,
|
|
52535
|
+
createConsoleEvent,
|
|
52536
|
+
captureStackTrace,
|
|
52537
|
+
send,
|
|
52538
|
+
setCaptureState,
|
|
52539
|
+
recordingStarted,
|
|
52540
|
+
recordingStopped,
|
|
52541
|
+
onAppHidden,
|
|
52542
|
+
onAppUnloaded,
|
|
52543
|
+
onPtmPaused,
|
|
52544
|
+
onPtmUnpaused,
|
|
52545
|
+
securityPolicyViolationFn,
|
|
52416
52546
|
get isCapturingConsoleLogs() {
|
|
52417
52547
|
return isCapturingConsoleLogs;
|
|
52418
52548
|
},
|
|
@@ -52429,16 +52559,16 @@ function ConsoleCapture() {
|
|
|
52429
52559
|
function initialize(pendo, PluginAPI) {
|
|
52430
52560
|
_ = pendo._;
|
|
52431
52561
|
pluginAPI = PluginAPI;
|
|
52432
|
-
|
|
52562
|
+
const { ConfigReader } = pluginAPI;
|
|
52433
52563
|
ConfigReader.addOption(CAPTURE_CONSOLE_CONFIG, [ConfigReader.sources.PENDO_CONFIG_SRC], false);
|
|
52434
|
-
|
|
52564
|
+
const captureConsoleEnabled = ConfigReader.get(CAPTURE_CONSOLE_CONFIG);
|
|
52435
52565
|
if (!captureConsoleEnabled)
|
|
52436
52566
|
return;
|
|
52437
52567
|
globalPendo = pendo;
|
|
52438
52568
|
buffer = new DevlogBuffer(pendo, pluginAPI);
|
|
52439
52569
|
transport = new DevlogTransport(pendo, pluginAPI);
|
|
52440
52570
|
sendQueue = new pluginAPI.SendQueue(transport.sendRequest.bind(transport));
|
|
52441
|
-
sendInterval = setInterval(
|
|
52571
|
+
sendInterval = setInterval(() => {
|
|
52442
52572
|
if (!sendQueue.failed()) {
|
|
52443
52573
|
send();
|
|
52444
52574
|
}
|
|
@@ -52464,19 +52594,17 @@ function ConsoleCapture() {
|
|
|
52464
52594
|
function onPtmUnpaused() {
|
|
52465
52595
|
isPtmPaused = false;
|
|
52466
52596
|
if (!buffer.isEmpty()) {
|
|
52467
|
-
for (
|
|
52468
|
-
|
|
52469
|
-
pluginAPI.Events.eventCaptured.trigger(event_1);
|
|
52597
|
+
for (const event of buffer.events) {
|
|
52598
|
+
pluginAPI.Events.eventCaptured.trigger(event);
|
|
52470
52599
|
}
|
|
52471
52600
|
send();
|
|
52472
52601
|
}
|
|
52473
52602
|
}
|
|
52474
|
-
function setCaptureState(
|
|
52475
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.shouldCapture, shouldCapture = _c === void 0 ? false : _c, _d = _b.reason, reason = _d === void 0 ? '' : _d;
|
|
52603
|
+
function setCaptureState({ shouldCapture = false, reason = '' } = {}) {
|
|
52476
52604
|
if (shouldCapture === isCapturingConsoleLogs)
|
|
52477
52605
|
return;
|
|
52478
52606
|
isCapturingConsoleLogs = shouldCapture;
|
|
52479
|
-
pluginAPI.log.info(
|
|
52607
|
+
pluginAPI.log.info(`[ConsoleCapture] Console log capture ${shouldCapture ? 'started' : 'stopped'}${reason ? `: ${reason}` : ''}`);
|
|
52480
52608
|
}
|
|
52481
52609
|
function recordingStarted() {
|
|
52482
52610
|
setCaptureState({ shouldCapture: true, reason: 'recording started' });
|
|
@@ -52496,12 +52624,12 @@ function ConsoleCapture() {
|
|
|
52496
52624
|
}
|
|
52497
52625
|
function addIntercepts() {
|
|
52498
52626
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52499
|
-
|
|
52627
|
+
const originalMethod = console[methodName];
|
|
52500
52628
|
if (!originalMethod)
|
|
52501
52629
|
return;
|
|
52502
52630
|
console[methodName] = _.wrap(originalMethod, function (originalFn) {
|
|
52503
52631
|
// slice 1 to omit originalFn
|
|
52504
|
-
|
|
52632
|
+
const args = _.toArray(arguments).slice(1);
|
|
52505
52633
|
originalFn.apply(console, args);
|
|
52506
52634
|
createConsoleEvent(args, methodName);
|
|
52507
52635
|
});
|
|
@@ -52513,10 +52641,10 @@ function ConsoleCapture() {
|
|
|
52513
52641
|
function securityPolicyViolationFn(evt) {
|
|
52514
52642
|
if (!evt || typeof evt !== 'object')
|
|
52515
52643
|
return;
|
|
52516
|
-
|
|
52517
|
-
|
|
52518
|
-
|
|
52519
|
-
|
|
52644
|
+
const { blockedURI, violatedDirective, effectiveDirective, disposition, originalPolicy } = evt;
|
|
52645
|
+
const directive = violatedDirective || effectiveDirective;
|
|
52646
|
+
const isReportOnly = disposition === 'report';
|
|
52647
|
+
const message = createCspViolationMessage(blockedURI, directive, isReportOnly, originalPolicy);
|
|
52520
52648
|
if (isReportOnly) {
|
|
52521
52649
|
createConsoleEvent([message], 'warn', { skipStackTrace: true, skipScrubPII: true });
|
|
52522
52650
|
}
|
|
@@ -52524,13 +52652,12 @@ function ConsoleCapture() {
|
|
|
52524
52652
|
createConsoleEvent([message], 'error', { skipStackTrace: true, skipScrubPII: true });
|
|
52525
52653
|
}
|
|
52526
52654
|
}
|
|
52527
|
-
function createConsoleEvent(args, methodName,
|
|
52528
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.skipStackTrace, skipStackTrace = _c === void 0 ? false : _c, _d = _b.skipScrubPII, skipScrubPII = _d === void 0 ? false : _d;
|
|
52655
|
+
function createConsoleEvent(args, methodName, { skipStackTrace = false, skipScrubPII = false } = {}) {
|
|
52529
52656
|
if (!isCapturingConsoleLogs || !args || args.length === 0 || !_.contains(CONSOLE_METHODS, methodName))
|
|
52530
52657
|
return;
|
|
52531
52658
|
// stringify args
|
|
52532
|
-
|
|
52533
|
-
|
|
52659
|
+
let message = _.compact(_.map(args, arg => {
|
|
52660
|
+
let stringifiedArg;
|
|
52534
52661
|
try {
|
|
52535
52662
|
stringifiedArg = stringify(arg);
|
|
52536
52663
|
}
|
|
@@ -52542,22 +52669,22 @@ function ConsoleCapture() {
|
|
|
52542
52669
|
if (!message)
|
|
52543
52670
|
return;
|
|
52544
52671
|
// capture stack trace
|
|
52545
|
-
|
|
52672
|
+
let stackTrace = '';
|
|
52546
52673
|
if (!skipStackTrace) {
|
|
52547
|
-
|
|
52674
|
+
const maxStackFrames = methodName === 'error' ? 4 : 1;
|
|
52548
52675
|
stackTrace = captureStackTrace(maxStackFrames);
|
|
52549
52676
|
}
|
|
52550
52677
|
// truncate message and stack trace
|
|
52551
52678
|
message = truncate(message);
|
|
52552
52679
|
stackTrace = truncate(stackTrace);
|
|
52553
52680
|
// de-duplicate log
|
|
52554
|
-
|
|
52681
|
+
const logKey = generateLogKey(methodName, message, stackTrace);
|
|
52555
52682
|
if (isExistingDuplicateLog(logKey)) {
|
|
52556
52683
|
buffer.lastEvent.devLogCount++;
|
|
52557
52684
|
return;
|
|
52558
52685
|
}
|
|
52559
|
-
|
|
52560
|
-
|
|
52686
|
+
const devLogEnvelope = createDevLogEnvelope(pluginAPI, globalPendo);
|
|
52687
|
+
const consoleEvent = Object.assign(Object.assign({}, devLogEnvelope), { subType: DEV_LOG_SUB_TYPE, devLogLevel: methodName === 'log' ? 'info' : methodName, devLogMessage: skipScrubPII ? message : scrubPII({ string: message, _ }), devLogTrace: stackTrace, devLogCount: 1 });
|
|
52561
52688
|
if (!buffer.hasTokenAvailable())
|
|
52562
52689
|
return consoleEvent;
|
|
52563
52690
|
if (!isPtmPaused) {
|
|
@@ -52569,8 +52696,8 @@ function ConsoleCapture() {
|
|
|
52569
52696
|
}
|
|
52570
52697
|
function captureStackTrace(maxStackFrames) {
|
|
52571
52698
|
try {
|
|
52572
|
-
|
|
52573
|
-
return _.map(stackFrames,
|
|
52699
|
+
const stackFrames = ErrorStackParser.parse(new Error(), maxStackFrames);
|
|
52700
|
+
return _.map(stackFrames, frame => frame.toString()).join('\n');
|
|
52574
52701
|
}
|
|
52575
52702
|
catch (error) {
|
|
52576
52703
|
return '';
|
|
@@ -52582,22 +52709,21 @@ function ConsoleCapture() {
|
|
|
52582
52709
|
function updateLastLog(logKey) {
|
|
52583
52710
|
lastLogKey = logKey;
|
|
52584
52711
|
}
|
|
52585
|
-
function send(
|
|
52586
|
-
var _b = _a === void 0 ? {} : _a, _c = _b.unload, unload = _c === void 0 ? false : _c, _d = _b.hidden, hidden = _d === void 0 ? false : _d;
|
|
52712
|
+
function send({ unload = false, hidden = false } = {}) {
|
|
52587
52713
|
if (!buffer || buffer.isEmpty())
|
|
52588
52714
|
return;
|
|
52589
52715
|
if (!globalPendo.isSendingEvents()) {
|
|
52590
52716
|
buffer.clear();
|
|
52591
52717
|
return;
|
|
52592
52718
|
}
|
|
52593
|
-
|
|
52719
|
+
const payloads = buffer.pack();
|
|
52594
52720
|
if (!payloads || payloads.length === 0)
|
|
52595
52721
|
return;
|
|
52596
52722
|
if (unload || hidden) {
|
|
52597
52723
|
sendQueue.drain(payloads, unload);
|
|
52598
52724
|
}
|
|
52599
52725
|
else {
|
|
52600
|
-
sendQueue.push
|
|
52726
|
+
sendQueue.push(...payloads);
|
|
52601
52727
|
}
|
|
52602
52728
|
}
|
|
52603
52729
|
function teardown() {
|
|
@@ -52621,7 +52747,7 @@ function ConsoleCapture() {
|
|
|
52621
52747
|
_.each(CONSOLE_METHODS, function (methodName) {
|
|
52622
52748
|
if (!console[methodName])
|
|
52623
52749
|
return _.noop;
|
|
52624
|
-
|
|
52750
|
+
const unwrap = console[methodName]._pendoUnwrap;
|
|
52625
52751
|
if (_.isFunction(unwrap)) {
|
|
52626
52752
|
unwrap();
|
|
52627
52753
|
}
|
|
@@ -55084,46 +55210,42 @@ var _ = /*@__PURE__*/getDefaultExportFromCjs(underscoreExports);
|
|
|
55084
55210
|
|
|
55085
55211
|
var encodeURIComponent = _.isFunction(window.encodeURIComponent) ? window.encodeURIComponent : _.identity;
|
|
55086
55212
|
|
|
55087
|
-
|
|
55088
|
-
|
|
55089
|
-
|
|
55090
|
-
|
|
55091
|
-
|
|
55092
|
-
|
|
55093
|
-
|
|
55094
|
-
|
|
55213
|
+
const PREDICT_STEP_REGEX = /\$\$predict\$\$/;
|
|
55214
|
+
const DRAG_THRESHOLD = 5;
|
|
55215
|
+
const STYLE_ID = 'pendo-predict-plugin-styles';
|
|
55216
|
+
const GUIDE_BUTTON_IDENTIFIER = 'button:contains("token")';
|
|
55217
|
+
const pluginVersion = '1.0.1';
|
|
55218
|
+
const PREDICT_SANDBOX_PAGE = 'predict-sandbox.html';
|
|
55219
|
+
const getPredictBaseUrl = (designerServer) => designerServer.replace('app', 'predict');
|
|
55220
|
+
const EXTENSION_ORIGIN_REGEX = /^(chrome|moz|safari-web)-extension:\/\//;
|
|
55095
55221
|
/**
|
|
55096
55222
|
* When running inside the Pendo Launcher extension, a host page's CSP `frame-src`
|
|
55097
55223
|
* blocks embedding predict.pendo.io directly. The extension ships a web-accessible
|
|
55098
55224
|
* `predict-sandbox.html` relay (exempt from the page CSP) that we frame instead, passing
|
|
55099
55225
|
* the real predict URL via `?target=`. assetHost is the extension origin in that context.
|
|
55100
55226
|
*/
|
|
55101
|
-
|
|
55227
|
+
const getFrameWrapperBase = (pendo) => {
|
|
55102
55228
|
var _a;
|
|
55103
|
-
|
|
55229
|
+
const assetHost = ((_a = pendo === null || pendo === void 0 ? void 0 : pendo.getConfigValue) === null || _a === void 0 ? void 0 : _a.call(pendo, 'assetHost')) || '';
|
|
55104
55230
|
return EXTENSION_ORIGIN_REGEX.test(assetHost) ? assetHost.replace(/\/$/, '') : '';
|
|
55105
55231
|
};
|
|
55106
55232
|
/**
|
|
55107
55233
|
* Builds the iframe `src`. Outside the extension this is the raw predict URL; inside it,
|
|
55108
55234
|
* the predict URL is passed as `?target=` to the extension's web-accessible relay page.
|
|
55109
55235
|
*/
|
|
55110
|
-
|
|
55111
|
-
return wrapperBase ? "".concat(wrapperBase, "/").concat(PREDICT_SANDBOX_PAGE, "?target=").concat(encodeURIComponent(url)) : url;
|
|
55112
|
-
};
|
|
55236
|
+
const buildFrameSrc = (url, wrapperBase) => wrapperBase ? `${wrapperBase}/${PREDICT_SANDBOX_PAGE}?target=${encodeURIComponent(url)}` : url;
|
|
55113
55237
|
/**
|
|
55114
55238
|
* Target origin for outbound postMessage. When wrapped, the relay frame is same-origin
|
|
55115
55239
|
* with the extension (`wrapperBase`), so we address it explicitly rather than broadcasting
|
|
55116
55240
|
* with '*' — keeping the auth token off any wildcard. Unwrapped, we post straight to predict.
|
|
55117
55241
|
*/
|
|
55118
|
-
|
|
55119
|
-
|
|
55120
|
-
|
|
55121
|
-
|
|
55122
|
-
|
|
55123
|
-
|
|
55124
|
-
|
|
55125
|
-
for (var i = 0; i < entries.length; i++) {
|
|
55126
|
-
var _a = entries[i], key = _a[0], value = _a[1];
|
|
55242
|
+
const getFrameTargetOrigin = (wrapperBase, predictBaseUrl) => wrapperBase || predictBaseUrl;
|
|
55243
|
+
const $ = (id) => document.getElementById(id);
|
|
55244
|
+
const createElement = (tag, attrs = {}, parent = null) => {
|
|
55245
|
+
const el = document.createElement(tag);
|
|
55246
|
+
const entries = Object.entries(attrs);
|
|
55247
|
+
for (let i = 0; i < entries.length; i++) {
|
|
55248
|
+
const [key, value] = entries[i];
|
|
55127
55249
|
if (key === 'className')
|
|
55128
55250
|
el.className = value;
|
|
55129
55251
|
else if (key === 'innerHTML')
|
|
@@ -55135,28 +55257,70 @@ var createElement = function (tag, attrs, parent) {
|
|
|
55135
55257
|
parent.appendChild(el);
|
|
55136
55258
|
return el;
|
|
55137
55259
|
};
|
|
55138
|
-
|
|
55139
|
-
|
|
55140
|
-
var styleId = "".concat(STYLE_ID, "-").concat(pendoContainerId);
|
|
55260
|
+
const injectStyles = (pendoContainerId, log = () => { }) => {
|
|
55261
|
+
const styleId = `${STYLE_ID}-${pendoContainerId}`;
|
|
55141
55262
|
if ($(styleId)) {
|
|
55142
|
-
log(
|
|
55263
|
+
log(`[predict] style already exists, skipping: ${styleId}`);
|
|
55143
55264
|
return;
|
|
55144
55265
|
}
|
|
55145
|
-
log(
|
|
55266
|
+
log(`[predict] injecting styles: ${styleId}`);
|
|
55146
55267
|
createElement('style', {
|
|
55147
55268
|
id: styleId,
|
|
55148
|
-
textContent:
|
|
55269
|
+
textContent: `
|
|
55270
|
+
#${pendoContainerId} {
|
|
55271
|
+
display: none !important;
|
|
55272
|
+
}
|
|
55273
|
+
.frame-explanation {
|
|
55274
|
+
aspect-ratio: 16/9; overflow: hidden; min-height: 300px;
|
|
55275
|
+
width: 100vw; height: 100vh; background: transparent;
|
|
55276
|
+
position: fixed; bottom: 0; right: 0; z-index: 1; border: none;
|
|
55277
|
+
visibility: hidden; opacity: 0; pointer-events: none;
|
|
55278
|
+
transition: opacity 0.1s ease-out, visibility 0s linear 0.1s;
|
|
55279
|
+
display: none;
|
|
55280
|
+
}
|
|
55281
|
+
.frame-explanation.is-visible {
|
|
55282
|
+
z-index: 999999;
|
|
55283
|
+
visibility: visible; opacity: 1; pointer-events: auto;
|
|
55284
|
+
transition: opacity 0.1s ease-out, visibility 0s linear 0s;
|
|
55285
|
+
}
|
|
55286
|
+
.frame-explanation.is-exists {
|
|
55287
|
+
display: block !important;
|
|
55288
|
+
}
|
|
55289
|
+
.floating-modal-container {
|
|
55290
|
+
position: fixed; top: 20px; right: 20px; z-index: 500000;
|
|
55291
|
+
visibility: hidden; opacity: 0; pointer-events: none;
|
|
55292
|
+
transition: opacity 0.1s ease-out, visibility 0s linear 0.1s;
|
|
55293
|
+
border-radius: 8px; box-shadow: 0px 4px 12px 0px rgba(0,0,0,0.15);
|
|
55294
|
+
overflow: hidden; width: 384px; height: 176px;
|
|
55295
|
+
}
|
|
55296
|
+
.floating-modal-container.is-visible {
|
|
55297
|
+
visibility: visible; opacity: 1; pointer-events: auto;
|
|
55298
|
+
transition: opacity 0.1s ease-out, visibility 0s linear 0s;
|
|
55299
|
+
}
|
|
55300
|
+
.floating-modal-container.is-dragging { will-change: left, top; }
|
|
55301
|
+
.floating-modal-drag-handle {
|
|
55302
|
+
position: absolute; left: 50%; transform: translateX(-50%);
|
|
55303
|
+
top: 5px; width: calc(100% - 46px); min-width: 166px; height: 17px;
|
|
55304
|
+
z-index: 9999; transition: left 0.2s ease, right 0.2s ease;
|
|
55305
|
+
display: flex; justify-content: center; align-items: center;
|
|
55306
|
+
}
|
|
55307
|
+
.floating-modal-drag-handle svg g { fill: #A0A0A0; }
|
|
55308
|
+
.floating-modal-drag-handle:hover { cursor: grab; }
|
|
55309
|
+
.floating-modal-drag-handle:hover svg g { fill: #1f2937; }
|
|
55310
|
+
.floating-modal-drag-handle.is-dragging { cursor: grabbing; }
|
|
55311
|
+
.floating-modal-drag-handle.is-collapsed { top: 0px; }
|
|
55312
|
+
.frame-floating-modal { width: 100%; height: 100%; background: white; border: none; display: block; }
|
|
55313
|
+
`
|
|
55149
55314
|
}, document.head);
|
|
55150
55315
|
};
|
|
55151
|
-
|
|
55316
|
+
const getRecordIdFromUrl = (recordRegex, log = () => { }) => {
|
|
55152
55317
|
var _a;
|
|
55153
|
-
|
|
55154
|
-
|
|
55155
|
-
|
|
55156
|
-
log("[predict] recordId found: ".concat(recordId));
|
|
55318
|
+
const match = window.location.href.match(recordRegex);
|
|
55319
|
+
const recordId = (_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : null;
|
|
55320
|
+
log(`[predict] recordId found: ${recordId}`);
|
|
55157
55321
|
return recordId;
|
|
55158
55322
|
};
|
|
55159
|
-
|
|
55323
|
+
const safeStringify = (value, fallback) => {
|
|
55160
55324
|
try {
|
|
55161
55325
|
return JSON.stringify(value);
|
|
55162
55326
|
}
|
|
@@ -55164,22 +55328,21 @@ var safeStringify = function (value, fallback) {
|
|
|
55164
55328
|
return fallback !== null && fallback !== void 0 ? fallback : '';
|
|
55165
55329
|
}
|
|
55166
55330
|
};
|
|
55167
|
-
|
|
55168
|
-
if (log === void 0) { log = function () { }; }
|
|
55331
|
+
const safeParse = (value, fallback, log = () => { }) => {
|
|
55169
55332
|
try {
|
|
55170
55333
|
return JSON.parse(value);
|
|
55171
55334
|
}
|
|
55172
55335
|
catch (error) {
|
|
55173
|
-
log(
|
|
55336
|
+
log(`[predict] JSON parse error: ${error}`);
|
|
55174
55337
|
return fallback;
|
|
55175
55338
|
}
|
|
55176
55339
|
};
|
|
55177
|
-
|
|
55178
|
-
|
|
55179
|
-
|
|
55340
|
+
const buildQueryParams = (params) => {
|
|
55341
|
+
const urlParams = new URLSearchParams();
|
|
55342
|
+
const entries = Object.entries(params);
|
|
55180
55343
|
urlParams.set('pluginVersion', pluginVersion);
|
|
55181
|
-
for (
|
|
55182
|
-
|
|
55344
|
+
for (let i = 0; i < entries.length; i++) {
|
|
55345
|
+
const [key, value] = entries[i];
|
|
55183
55346
|
if (value != null) {
|
|
55184
55347
|
urlParams.set(key, typeof value === 'object' ? safeStringify(value) : String(value));
|
|
55185
55348
|
}
|
|
@@ -55187,17 +55350,17 @@ var buildQueryParams = function (params) {
|
|
|
55187
55350
|
return urlParams.toString();
|
|
55188
55351
|
};
|
|
55189
55352
|
// ----- Drag & Drop -----
|
|
55190
|
-
|
|
55191
|
-
|
|
55192
|
-
|
|
55193
|
-
|
|
55194
|
-
|
|
55195
|
-
|
|
55196
|
-
|
|
55197
|
-
|
|
55198
|
-
|
|
55199
|
-
|
|
55200
|
-
|
|
55353
|
+
const setupDragAndDrop = (handle, container, frameTargetOrigin) => {
|
|
55354
|
+
let isDragging = false;
|
|
55355
|
+
let hasMoved = false;
|
|
55356
|
+
let isCollapsed = false;
|
|
55357
|
+
let startX = 0;
|
|
55358
|
+
let startY = 0;
|
|
55359
|
+
let initialLeft = 0;
|
|
55360
|
+
let initialTop = 0;
|
|
55361
|
+
let rafId = null;
|
|
55362
|
+
const iframe = container.querySelector('iframe');
|
|
55363
|
+
const onMouseDown = (e) => {
|
|
55201
55364
|
if (e.button !== 0)
|
|
55202
55365
|
return;
|
|
55203
55366
|
e.preventDefault();
|
|
@@ -55207,35 +55370,35 @@ var setupDragAndDrop = function (handle, container, frameTargetOrigin) {
|
|
|
55207
55370
|
container.classList.add('is-dragging');
|
|
55208
55371
|
if (iframe)
|
|
55209
55372
|
iframe.style.pointerEvents = 'none';
|
|
55210
|
-
|
|
55373
|
+
const rect = container.getBoundingClientRect();
|
|
55211
55374
|
initialLeft = rect.left;
|
|
55212
55375
|
initialTop = rect.top;
|
|
55213
|
-
container.style.left =
|
|
55376
|
+
container.style.left = `${initialLeft}px`;
|
|
55214
55377
|
container.style.right = 'auto';
|
|
55215
55378
|
startX = e.clientX;
|
|
55216
55379
|
startY = e.clientY;
|
|
55217
55380
|
document.addEventListener('mousemove', onMouseMove);
|
|
55218
55381
|
document.addEventListener('mouseup', onMouseUp);
|
|
55219
55382
|
};
|
|
55220
|
-
|
|
55383
|
+
const onMouseMove = (e) => {
|
|
55221
55384
|
if (!isDragging)
|
|
55222
55385
|
return;
|
|
55223
|
-
|
|
55224
|
-
|
|
55386
|
+
const deltaX = e.clientX - startX;
|
|
55387
|
+
const deltaY = e.clientY - startY;
|
|
55225
55388
|
if (Math.abs(deltaX) > DRAG_THRESHOLD || Math.abs(deltaY) > DRAG_THRESHOLD) {
|
|
55226
55389
|
hasMoved = true;
|
|
55227
55390
|
}
|
|
55228
55391
|
if (rafId)
|
|
55229
55392
|
cancelAnimationFrame(rafId);
|
|
55230
|
-
rafId = requestAnimationFrame(
|
|
55231
|
-
|
|
55232
|
-
|
|
55233
|
-
|
|
55234
|
-
container.style.left =
|
|
55235
|
-
container.style.top =
|
|
55393
|
+
rafId = requestAnimationFrame(() => {
|
|
55394
|
+
const rect = container.getBoundingClientRect();
|
|
55395
|
+
const newLeft = Math.max(0, Math.min(initialLeft + deltaX, window.innerWidth - rect.width));
|
|
55396
|
+
const newTop = Math.max(0, Math.min(initialTop + deltaY, window.innerHeight - rect.height));
|
|
55397
|
+
container.style.left = `${newLeft}px`;
|
|
55398
|
+
container.style.top = `${newTop}px`;
|
|
55236
55399
|
});
|
|
55237
55400
|
};
|
|
55238
|
-
|
|
55401
|
+
const onMouseUp = (e) => {
|
|
55239
55402
|
var _a;
|
|
55240
55403
|
if (!isDragging)
|
|
55241
55404
|
return;
|
|
@@ -55253,12 +55416,12 @@ var setupDragAndDrop = function (handle, container, frameTargetOrigin) {
|
|
|
55253
55416
|
(_a = iframe === null || iframe === void 0 ? void 0 : iframe.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage({ type: 'TRIGGER_EXPAND' }, frameTargetOrigin);
|
|
55254
55417
|
}
|
|
55255
55418
|
};
|
|
55256
|
-
handle.setCollapsedState =
|
|
55419
|
+
handle.setCollapsedState = (collapsed) => {
|
|
55257
55420
|
isCollapsed = collapsed;
|
|
55258
55421
|
handle.classList.toggle('is-collapsed', collapsed);
|
|
55259
55422
|
};
|
|
55260
55423
|
handle.addEventListener('mousedown', onMouseDown);
|
|
55261
|
-
handle.cleanup =
|
|
55424
|
+
handle.cleanup = () => {
|
|
55262
55425
|
handle.removeEventListener('mousedown', onMouseDown);
|
|
55263
55426
|
document.removeEventListener('mousemove', onMouseMove);
|
|
55264
55427
|
document.removeEventListener('mouseup', onMouseUp);
|
|
@@ -55268,13 +55431,12 @@ var setupDragAndDrop = function (handle, container, frameTargetOrigin) {
|
|
|
55268
55431
|
return handle;
|
|
55269
55432
|
};
|
|
55270
55433
|
// ----- Explanation Iframe Creation -----
|
|
55271
|
-
|
|
55272
|
-
var
|
|
55273
|
-
|
|
55274
|
-
|
|
55275
|
-
|
|
55276
|
-
|
|
55277
|
-
var params = buildQueryParams(configuration);
|
|
55434
|
+
const createExplanationIframe = ({ analysisId, recordId, configuration, predictBaseUrl, wrapperBase = '' }) => {
|
|
55435
|
+
var _a;
|
|
55436
|
+
const frameId = `frameExplanation-${analysisId}`;
|
|
55437
|
+
(_a = $(frameId)) === null || _a === void 0 ? void 0 : _a.remove();
|
|
55438
|
+
const base = `${predictBaseUrl}/external/analysis/${analysisId}/prediction/drilldown/${recordId}`;
|
|
55439
|
+
const params = buildQueryParams(configuration);
|
|
55278
55440
|
createElement('iframe', {
|
|
55279
55441
|
id: frameId,
|
|
55280
55442
|
className: 'frame-explanation',
|
|
@@ -55282,24 +55444,28 @@ var createExplanationIframe = function (_a) {
|
|
|
55282
55444
|
loading: 'lazy',
|
|
55283
55445
|
referrerPolicy: 'strict-origin-when-cross-origin',
|
|
55284
55446
|
allowFullscreen: true,
|
|
55285
|
-
src: buildFrameSrc(
|
|
55447
|
+
src: buildFrameSrc(`${base}?${params}`, wrapperBase)
|
|
55286
55448
|
}, document.body);
|
|
55287
55449
|
};
|
|
55288
55450
|
// ----- Floating Modal Creation -----
|
|
55289
|
-
|
|
55290
|
-
var
|
|
55291
|
-
|
|
55292
|
-
|
|
55293
|
-
|
|
55294
|
-
|
|
55295
|
-
}
|
|
55296
|
-
|
|
55297
|
-
var dragHandle = createElement('div', {
|
|
55451
|
+
const createFloatingModal = ({ recordId, configuration, predictBaseUrl, wrapperBase = '' }) => {
|
|
55452
|
+
var _a;
|
|
55453
|
+
const flatIds = (_a = configuration.analysisIds) === null || _a === void 0 ? void 0 : _a.flat(Infinity);
|
|
55454
|
+
for (let i = 0; i < flatIds.length; i++) {
|
|
55455
|
+
createExplanationIframe({ analysisId: flatIds[i], recordId, configuration, predictBaseUrl, wrapperBase });
|
|
55456
|
+
}
|
|
55457
|
+
const container = createElement('div', { id: 'floatingModalContainer', className: 'floating-modal-container' }, document.body);
|
|
55458
|
+
const dragHandle = createElement('div', {
|
|
55298
55459
|
className: 'floating-modal-drag-handle',
|
|
55299
|
-
innerHTML:
|
|
55460
|
+
innerHTML: `<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
|
|
55461
|
+
<g fill="#EBEBEB">
|
|
55462
|
+
<circle cx="3.33" cy="6" r="1.5"/><circle cx="8" cy="6" r="1.5"/><circle cx="12.67" cy="6" r="1.5"/>
|
|
55463
|
+
<circle cx="3.33" cy="10" r="1.5"/><circle cx="8" cy="10" r="1.5"/><circle cx="12.67" cy="10" r="1.5"/>
|
|
55464
|
+
</g>
|
|
55465
|
+
</svg>`
|
|
55300
55466
|
}, container);
|
|
55301
|
-
|
|
55302
|
-
|
|
55467
|
+
const baseUrl = `${predictBaseUrl}/external/analysis/prediction/summary/${recordId}`;
|
|
55468
|
+
const params = buildQueryParams(configuration);
|
|
55303
55469
|
createElement('iframe', {
|
|
55304
55470
|
id: 'frameFloatingModal',
|
|
55305
55471
|
className: 'frame-floating-modal',
|
|
@@ -55307,133 +55473,130 @@ var createFloatingModal = function (_a) {
|
|
|
55307
55473
|
referrerPolicy: 'strict-origin-when-cross-origin',
|
|
55308
55474
|
allowFullscreen: true,
|
|
55309
55475
|
title: 'Floating Modal',
|
|
55310
|
-
src: buildFrameSrc(
|
|
55476
|
+
src: buildFrameSrc(`${baseUrl}?${params}`, wrapperBase)
|
|
55311
55477
|
}, container);
|
|
55312
|
-
|
|
55478
|
+
const frameTargetOrigin = getFrameTargetOrigin(wrapperBase, predictBaseUrl);
|
|
55313
55479
|
container.dragHandle = setupDragAndDrop(dragHandle, container, frameTargetOrigin);
|
|
55314
|
-
return
|
|
55480
|
+
return () => {
|
|
55315
55481
|
var _a, _b;
|
|
55316
55482
|
(_b = (_a = container.dragHandle) === null || _a === void 0 ? void 0 : _a.cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
55317
55483
|
container.remove();
|
|
55318
|
-
for (
|
|
55319
|
-
|
|
55484
|
+
for (let i = 0; i < flatIds.length; i++) {
|
|
55485
|
+
const frame = $(`frameExplanation-${flatIds[i]}`);
|
|
55320
55486
|
if (frame)
|
|
55321
55487
|
frame.remove();
|
|
55322
55488
|
}
|
|
55323
55489
|
};
|
|
55324
55490
|
};
|
|
55325
|
-
|
|
55326
|
-
|
|
55327
|
-
|
|
55328
|
-
|
|
55329
|
-
|
|
55330
|
-
var _b;
|
|
55331
|
-
var origin = _a.origin, data = _a.data;
|
|
55491
|
+
const setupMessageListener = ({ token, forceAccountId, cleanup, pendo, predictBaseUrl, wrapperBase = '' }) => {
|
|
55492
|
+
const frameTargetOrigin = getFrameTargetOrigin(wrapperBase, predictBaseUrl);
|
|
55493
|
+
const isAllowedOrigin = (origin) => origin === predictBaseUrl || (!!wrapperBase && origin === wrapperBase);
|
|
55494
|
+
const messageHandler = ({ origin, data }) => {
|
|
55495
|
+
var _a;
|
|
55332
55496
|
if (!isAllowedOrigin(origin) || !data || typeof data !== 'object')
|
|
55333
55497
|
return;
|
|
55334
|
-
|
|
55335
|
-
|
|
55336
|
-
|
|
55337
|
-
|
|
55498
|
+
const { type, analysisId, height, width } = data;
|
|
55499
|
+
const explanationFrame = $(`frameExplanation-${analysisId}`);
|
|
55500
|
+
const floatingModal = $('floatingModalContainer');
|
|
55501
|
+
const setFloatingModalSize = () => {
|
|
55338
55502
|
if (floatingModal) {
|
|
55339
|
-
floatingModal.style.height =
|
|
55340
|
-
floatingModal.style.width =
|
|
55503
|
+
floatingModal.style.height = `${height}px`;
|
|
55504
|
+
floatingModal.style.width = `${width}px`;
|
|
55341
55505
|
}
|
|
55342
55506
|
};
|
|
55343
|
-
|
|
55507
|
+
const setFloatingModalCollapsedState = (collapsed) => {
|
|
55344
55508
|
var _a, _b;
|
|
55345
55509
|
if (floatingModal)
|
|
55346
55510
|
(_b = (_a = floatingModal.dragHandle) === null || _a === void 0 ? void 0 : _a.setCollapsedState) === null || _b === void 0 ? void 0 : _b.call(_a, collapsed);
|
|
55347
55511
|
};
|
|
55348
|
-
|
|
55349
|
-
MODAL_INITIALIZED:
|
|
55512
|
+
const actions = {
|
|
55513
|
+
MODAL_INITIALIZED: () => {
|
|
55350
55514
|
var _a, _b, _c;
|
|
55351
|
-
|
|
55515
|
+
const iframe = $('frameFloatingModal');
|
|
55352
55516
|
if (iframe) {
|
|
55353
|
-
|
|
55354
|
-
|
|
55355
|
-
|
|
55517
|
+
let idToken = null;
|
|
55518
|
+
let extensionAPIKeys = null;
|
|
55519
|
+
const retrieveIDPToken = pendo.getConfigValue('retrieveIDPToken');
|
|
55356
55520
|
if (pendo._.isFunction(retrieveIDPToken)) {
|
|
55357
|
-
|
|
55521
|
+
const result = retrieveIDPToken();
|
|
55358
55522
|
if (result) {
|
|
55359
55523
|
idToken = result.idToken;
|
|
55360
55524
|
extensionAPIKeys = result.extensionAPIKeys;
|
|
55361
55525
|
}
|
|
55362
55526
|
}
|
|
55363
|
-
|
|
55364
|
-
|
|
55365
|
-
(_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage({ type: 'TOKEN_RECEIVED', token
|
|
55527
|
+
const visitorId = (_a = pendo === null || pendo === void 0 ? void 0 : pendo.getVisitorId) === null || _a === void 0 ? void 0 : _a.call(pendo);
|
|
55528
|
+
const accountId = forceAccountId !== null && forceAccountId !== void 0 ? forceAccountId : (_b = pendo === null || pendo === void 0 ? void 0 : pendo.getAccountId) === null || _b === void 0 ? void 0 : _b.call(pendo);
|
|
55529
|
+
(_c = iframe.contentWindow) === null || _c === void 0 ? void 0 : _c.postMessage({ type: 'TOKEN_RECEIVED', token, idToken, extensionAPIKeys, visitorId, accountId }, frameTargetOrigin);
|
|
55366
55530
|
}
|
|
55367
55531
|
},
|
|
55368
|
-
OPEN_EXPLANATION:
|
|
55532
|
+
OPEN_EXPLANATION: () => {
|
|
55369
55533
|
var _a;
|
|
55370
55534
|
explanationFrame === null || explanationFrame === void 0 ? void 0 : explanationFrame.classList.add('is-visible');
|
|
55371
55535
|
(_a = explanationFrame === null || explanationFrame === void 0 ? void 0 : explanationFrame.contentWindow) === null || _a === void 0 ? void 0 : _a.postMessage(data, frameTargetOrigin);
|
|
55372
55536
|
},
|
|
55373
|
-
CLOSE_EXPLANATION:
|
|
55374
|
-
AUTH_ERROR_EXPLANATION:
|
|
55537
|
+
CLOSE_EXPLANATION: () => explanationFrame === null || explanationFrame === void 0 ? void 0 : explanationFrame.classList.remove('is-visible'),
|
|
55538
|
+
AUTH_ERROR_EXPLANATION: () => {
|
|
55375
55539
|
explanationFrame === null || explanationFrame === void 0 ? void 0 : explanationFrame.classList.remove('is-visible');
|
|
55376
|
-
|
|
55540
|
+
const iframe = $('frameFloatingModal');
|
|
55377
55541
|
// eslint-disable-next-line no-self-assign
|
|
55378
55542
|
if (iframe)
|
|
55379
55543
|
iframe.src = iframe.src;
|
|
55380
55544
|
},
|
|
55381
|
-
DATA_READY:
|
|
55545
|
+
DATA_READY: () => {
|
|
55382
55546
|
floatingModal === null || floatingModal === void 0 ? void 0 : floatingModal.classList.add('is-visible');
|
|
55383
55547
|
setFloatingModalSize();
|
|
55384
55548
|
// Use analysisIds from the message data if available, otherwise use all IDs
|
|
55385
|
-
|
|
55386
|
-
for (
|
|
55387
|
-
|
|
55549
|
+
const idsToShow = data.analysisIds || [];
|
|
55550
|
+
for (let i = 0; i < idsToShow.length; i++) {
|
|
55551
|
+
const frame = $(`frameExplanation-${idsToShow[i]}`);
|
|
55388
55552
|
if (frame)
|
|
55389
55553
|
frame.classList.add('is-exists');
|
|
55390
55554
|
}
|
|
55391
55555
|
},
|
|
55392
|
-
AUTH_ERROR:
|
|
55556
|
+
AUTH_ERROR: () => {
|
|
55393
55557
|
floatingModal === null || floatingModal === void 0 ? void 0 : floatingModal.classList.add('is-visible');
|
|
55394
55558
|
setFloatingModalSize();
|
|
55395
55559
|
},
|
|
55396
55560
|
CLOSE_FLOATING_MODAL: cleanup,
|
|
55397
|
-
EXPAND_FLOATING_MODAL:
|
|
55561
|
+
EXPAND_FLOATING_MODAL: () => {
|
|
55398
55562
|
setFloatingModalSize();
|
|
55399
55563
|
setFloatingModalCollapsedState(false);
|
|
55400
55564
|
},
|
|
55401
|
-
COLLAPSE_FLOATING_MODAL:
|
|
55565
|
+
COLLAPSE_FLOATING_MODAL: () => {
|
|
55402
55566
|
setFloatingModalSize();
|
|
55403
55567
|
setFloatingModalCollapsedState(true);
|
|
55404
55568
|
}
|
|
55405
55569
|
};
|
|
55406
55570
|
if (type && type in actions) {
|
|
55407
|
-
(
|
|
55571
|
+
(_a = actions === null || actions === void 0 ? void 0 : actions[type]) === null || _a === void 0 ? void 0 : _a.call(actions);
|
|
55408
55572
|
}
|
|
55409
55573
|
};
|
|
55410
55574
|
window.addEventListener('message', messageHandler);
|
|
55411
|
-
return
|
|
55575
|
+
return () => window.removeEventListener('message', messageHandler);
|
|
55412
55576
|
};
|
|
55413
|
-
|
|
55414
|
-
var
|
|
55415
|
-
var step = _a.step, pendo = _a.pendo, cleanupArray = _a.cleanupArray, cleanup = _a.cleanup, log = _a.log, designerServer = _a.designerServer;
|
|
55577
|
+
const predictGuidesScript = ({ step, pendo, cleanupArray, cleanup, log, designerServer }) => {
|
|
55578
|
+
var _a;
|
|
55416
55579
|
log('[predict] initializing');
|
|
55417
55580
|
// Before anything else, inject styles so that the guide will be hidden
|
|
55418
|
-
|
|
55581
|
+
const pendoContainerId = step === null || step === void 0 ? void 0 : step.containerId;
|
|
55419
55582
|
injectStyles(pendoContainerId, log);
|
|
55420
55583
|
if (cleanupArray.length > 0) {
|
|
55421
55584
|
log('[predict] cleanupArray is not empty');
|
|
55422
55585
|
return;
|
|
55423
55586
|
}
|
|
55424
55587
|
// ----- Extract Configuration -----
|
|
55425
|
-
|
|
55588
|
+
const guideButton = (_a = step.guideElement.find(GUIDE_BUTTON_IDENTIFIER)) === null || _a === void 0 ? void 0 : _a[0];
|
|
55426
55589
|
if (!guideButton) {
|
|
55427
55590
|
log('[predict] no guide button found, aborting');
|
|
55428
55591
|
return;
|
|
55429
55592
|
}
|
|
55430
|
-
|
|
55593
|
+
const _b = safeParse(guideButton.textContent, {}, log), { token } = _b, configuration = __rest(_b, ["token"]);
|
|
55431
55594
|
if (!configuration || !token) {
|
|
55432
55595
|
log('[predict] no configuration found, aborting');
|
|
55433
55596
|
return;
|
|
55434
55597
|
}
|
|
55435
|
-
|
|
55436
|
-
|
|
55598
|
+
const recordRegex = new RegExp(`/${configuration.recordRegexName}/([a-zA-Z0-9]+)(?:/|$)`);
|
|
55599
|
+
const recordId = getRecordIdFromUrl(recordRegex, log);
|
|
55437
55600
|
if (!recordId) {
|
|
55438
55601
|
log('[predict] no recordId found in URL, aborting');
|
|
55439
55602
|
return;
|
|
@@ -55442,11 +55605,11 @@ var predictGuidesScript = function (_a) {
|
|
|
55442
55605
|
log('[predict] no designerServer found, aborting');
|
|
55443
55606
|
return;
|
|
55444
55607
|
}
|
|
55445
|
-
|
|
55446
|
-
|
|
55447
|
-
log(
|
|
55448
|
-
cleanupArray.push(setupMessageListener({ token
|
|
55449
|
-
cleanupArray.push(createFloatingModal({ recordId
|
|
55608
|
+
const predictBaseUrl = getPredictBaseUrl(designerServer);
|
|
55609
|
+
const wrapperBase = getFrameWrapperBase(pendo);
|
|
55610
|
+
log(`[predict] predictBaseUrl: ${predictBaseUrl}${wrapperBase ? `, wrapping via ${wrapperBase}` : ''}`);
|
|
55611
|
+
cleanupArray.push(setupMessageListener({ token, forceAccountId: configuration === null || configuration === void 0 ? void 0 : configuration.forceAccountId, cleanup, pendo, predictBaseUrl, wrapperBase }));
|
|
55612
|
+
cleanupArray.push(createFloatingModal({ recordId, configuration, predictBaseUrl, wrapperBase }));
|
|
55450
55613
|
};
|
|
55451
55614
|
|
|
55452
55615
|
const PredictGuides = () => {
|
|
@@ -55507,44 +55670,69 @@ const PredictGuides = () => {
|
|
|
55507
55670
|
};
|
|
55508
55671
|
};
|
|
55509
55672
|
|
|
55510
|
-
|
|
55511
|
-
|
|
55512
|
-
|
|
55513
|
-
|
|
55514
|
-
|
|
55515
|
-
|
|
55516
|
-
|
|
55517
|
-
|
|
55518
|
-
|
|
55519
|
-
|
|
55520
|
-
|
|
55521
|
-
|
|
55522
|
-
|
|
55523
|
-
|
|
55524
|
-
|
|
55525
|
-
|
|
55526
|
-
|
|
55673
|
+
const ASSISTANT_MESSAGE = 'assistantMessage';
|
|
55674
|
+
const CONVERSATION_ID_URL_PATTERN = 'conversationIdUrlPattern';
|
|
55675
|
+
const MESSAGE_CONTENT = 'messageContent';
|
|
55676
|
+
const MESSAGE_ID_ATTR = 'messageIdAttr';
|
|
55677
|
+
const MESSAGE_ID_PATTERN = 'messageIdPattern';
|
|
55678
|
+
const MODEL_USED_ATTR = 'modelUsedAttr';
|
|
55679
|
+
const REACTION_ACTIVE = 'reactionActive';
|
|
55680
|
+
const STREAMING_ACTIVE = 'streamingActive';
|
|
55681
|
+
const STREAMING_ACTIVE_ATTR = 'streamingActiveAttr';
|
|
55682
|
+
const THUMB_DOWN = 'thumbDown';
|
|
55683
|
+
const THUMB_UP = 'thumbUp';
|
|
55684
|
+
const TURN_CONTAINER = 'turnContainer';
|
|
55685
|
+
const USER_MESSAGE = 'userMessage';
|
|
55686
|
+
const CUSTOM_AGENT_ID_URL_PATTERN = 'customAgentIdUrlPattern';
|
|
55687
|
+
const CUSTOM_AGENT_ID = 'customAgentId';
|
|
55688
|
+
const CUSTOM_AGENT_NAME = 'customAgentName';
|
|
55689
|
+
const REQUIRED_SELECTORS = [
|
|
55527
55690
|
ASSISTANT_MESSAGE,
|
|
55528
55691
|
CONVERSATION_ID_URL_PATTERN,
|
|
55529
55692
|
STREAMING_ACTIVE,
|
|
55530
55693
|
TURN_CONTAINER,
|
|
55531
55694
|
USER_MESSAGE
|
|
55532
55695
|
];
|
|
55533
|
-
|
|
55696
|
+
const SUPPORTED_PRESETS = [
|
|
55534
55697
|
'chatgpt-full',
|
|
55535
55698
|
'gemini-full',
|
|
55536
55699
|
'claude-full',
|
|
55537
55700
|
'copilot-full',
|
|
55538
55701
|
'copilot-m365-full'
|
|
55539
55702
|
];
|
|
55540
|
-
|
|
55541
|
-
|
|
55542
|
-
|
|
55543
|
-
|
|
55544
|
-
|
|
55545
|
-
|
|
55546
|
-
|
|
55547
|
-
|
|
55703
|
+
const STREAMING_END_SETTLE_MS = 500;
|
|
55704
|
+
const SUBMISSION_START_RETRY_MS = 1000;
|
|
55705
|
+
const SUBMISSION_START_MAX_ATTEMPTS = 4;
|
|
55706
|
+
const NEW_CONVERSATION_TTL_MS = 5 * 60 * 1000;
|
|
55707
|
+
const NEW_CONVERSATION_KEY = 'pendo_pca_new_conv';
|
|
55708
|
+
class DOMConversation {
|
|
55709
|
+
// Returns the list of required selector types that are missing or empty
|
|
55710
|
+
// in the given cssSelectors config. An empty array means the config is
|
|
55711
|
+
// valid for instantiation.
|
|
55712
|
+
static validateConfig(cssSelectors) {
|
|
55713
|
+
if (!Array.isArray(cssSelectors)) {
|
|
55714
|
+
return REQUIRED_SELECTORS.slice();
|
|
55715
|
+
}
|
|
55716
|
+
const present = new Set();
|
|
55717
|
+
for (const cfg of cssSelectors) {
|
|
55718
|
+
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
55719
|
+
continue;
|
|
55720
|
+
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
55721
|
+
try {
|
|
55722
|
+
RegExp(cfg.cssSelector);
|
|
55723
|
+
}
|
|
55724
|
+
catch (e) {
|
|
55725
|
+
continue;
|
|
55726
|
+
}
|
|
55727
|
+
}
|
|
55728
|
+
present.add(cfg.type);
|
|
55729
|
+
}
|
|
55730
|
+
return REQUIRED_SELECTORS.filter((r) => !present.has(r));
|
|
55731
|
+
}
|
|
55732
|
+
static supportedPreset(preset) {
|
|
55733
|
+
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
55734
|
+
}
|
|
55735
|
+
constructor(pendo, PluginAPI, id, cssSelectors) {
|
|
55548
55736
|
this.selectors = {};
|
|
55549
55737
|
this.listeners = [];
|
|
55550
55738
|
this.isActive = true;
|
|
@@ -55563,88 +55751,61 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55563
55751
|
this.Sizzle = pendo.Sizzle;
|
|
55564
55752
|
this.id = id;
|
|
55565
55753
|
if (!this._.isArray(cssSelectors)) {
|
|
55566
|
-
this.api.log.error(
|
|
55754
|
+
this.api.log.error(`cssSelectors must be an array, received: ${typeof cssSelectors}`);
|
|
55567
55755
|
cssSelectors = [];
|
|
55568
55756
|
}
|
|
55569
|
-
this._.each(cssSelectors,
|
|
55757
|
+
this._.each(cssSelectors, (cfg) => {
|
|
55570
55758
|
if (cfg && cfg.type) {
|
|
55571
|
-
|
|
55759
|
+
this.selectors[cfg.type] = cfg.cssSelector;
|
|
55572
55760
|
}
|
|
55573
55761
|
});
|
|
55574
55762
|
this.conversationIdRegex = new RegExp(this.selectors[CONVERSATION_ID_URL_PATTERN]);
|
|
55575
|
-
|
|
55763
|
+
const customAgentIdUrlPattern = this.selectors[CUSTOM_AGENT_ID_URL_PATTERN];
|
|
55576
55764
|
if (customAgentIdUrlPattern) { // this is optional
|
|
55577
55765
|
try {
|
|
55578
55766
|
this.customAgentIdRegex = new RegExp(customAgentIdUrlPattern);
|
|
55579
55767
|
}
|
|
55580
55768
|
catch (error) {
|
|
55581
|
-
this.api.log.error(
|
|
55769
|
+
this.api.log.error(`bad customAgentIdUrlPattern ${customAgentIdUrlPattern}`, { error });
|
|
55582
55770
|
}
|
|
55583
55771
|
}
|
|
55584
|
-
|
|
55772
|
+
const messageIdPattern = this.selectors[MESSAGE_ID_PATTERN];
|
|
55585
55773
|
if (messageIdPattern) { // optional: gates the request node until its id is fully rendered
|
|
55586
55774
|
try {
|
|
55587
55775
|
this.messageIdRegex = new RegExp(messageIdPattern);
|
|
55588
55776
|
}
|
|
55589
55777
|
catch (error) {
|
|
55590
|
-
this.api.log.error(
|
|
55778
|
+
this.api.log.error(`bad messageIdPattern ${messageIdPattern}`, { error });
|
|
55591
55779
|
}
|
|
55592
55780
|
}
|
|
55593
55781
|
this.root = document.body;
|
|
55594
55782
|
this.setupReactionListener();
|
|
55595
55783
|
this.setupStreamingObserver();
|
|
55596
55784
|
}
|
|
55597
|
-
|
|
55598
|
-
// in the given cssSelectors config. An empty array means the config is
|
|
55599
|
-
// valid for instantiation.
|
|
55600
|
-
DOMConversation.validateConfig = function (cssSelectors) {
|
|
55601
|
-
if (!Array.isArray(cssSelectors)) {
|
|
55602
|
-
return REQUIRED_SELECTORS.slice();
|
|
55603
|
-
}
|
|
55604
|
-
var present = new Set();
|
|
55605
|
-
for (var _i = 0, cssSelectors_1 = cssSelectors; _i < cssSelectors_1.length; _i++) {
|
|
55606
|
-
var cfg = cssSelectors_1[_i];
|
|
55607
|
-
if (!cfg || !cfg.type || !cfg.cssSelector)
|
|
55608
|
-
continue;
|
|
55609
|
-
if (cfg.type === CONVERSATION_ID_URL_PATTERN) {
|
|
55610
|
-
try {
|
|
55611
|
-
RegExp(cfg.cssSelector);
|
|
55612
|
-
}
|
|
55613
|
-
catch (e) {
|
|
55614
|
-
continue;
|
|
55615
|
-
}
|
|
55616
|
-
}
|
|
55617
|
-
present.add(cfg.type);
|
|
55618
|
-
}
|
|
55619
|
-
return REQUIRED_SELECTORS.filter(function (r) { return !present.has(r); });
|
|
55620
|
-
};
|
|
55621
|
-
DOMConversation.supportedPreset = function (preset) {
|
|
55622
|
-
return SUPPORTED_PRESETS.indexOf(preset) !== -1;
|
|
55623
|
-
};
|
|
55624
|
-
DOMConversation.prototype.setupReactionListener = function () {
|
|
55785
|
+
setupReactionListener() {
|
|
55625
55786
|
if (!this.findSelector(THUMB_UP) && !this.findSelector(THUMB_DOWN))
|
|
55626
55787
|
return;
|
|
55627
55788
|
this.reactionClickHandler = this.handleReactionClick.bind(this);
|
|
55628
55789
|
this.root.addEventListener('click', this.reactionClickHandler, true);
|
|
55629
|
-
}
|
|
55630
|
-
|
|
55631
|
-
|
|
55790
|
+
}
|
|
55791
|
+
handleReactionClick(evt) {
|
|
55792
|
+
const target = evt.target;
|
|
55632
55793
|
if (!target || target.nodeType !== 1)
|
|
55633
55794
|
return;
|
|
55634
|
-
|
|
55635
|
-
|
|
55636
|
-
|
|
55795
|
+
const upSelector = this.findSelector(THUMB_UP);
|
|
55796
|
+
const downSelector = this.findSelector(THUMB_DOWN);
|
|
55797
|
+
const thumb = this.dom(target).closest(`${upSelector}, ${downSelector}`);
|
|
55637
55798
|
if (!thumb.length)
|
|
55638
55799
|
return;
|
|
55639
|
-
|
|
55640
|
-
|
|
55641
|
-
|
|
55642
|
-
|
|
55643
|
-
|
|
55800
|
+
const isUp = this.Sizzle.matchesSelector(thumb[0], upSelector);
|
|
55801
|
+
const activeSelector = this.findSelector(REACTION_ACTIVE);
|
|
55802
|
+
const wasPressed = activeSelector && this.Sizzle.matchesSelector(thumb[0], activeSelector);
|
|
55803
|
+
const direction = isUp ? 'positive' : 'negative';
|
|
55804
|
+
const content = wasPressed ? 'unreact' : direction;
|
|
55644
55805
|
// the thumb may live inside the assistant message (e.g. copilot) or in a separate
|
|
55645
55806
|
// turn footer alongside it (e.g. chatgpt/gemini); handle both
|
|
55646
|
-
|
|
55647
|
-
|
|
55807
|
+
const assistantSelector = this.findSelector(ASSISTANT_MESSAGE);
|
|
55808
|
+
let assistantNode = thumb.closest(assistantSelector);
|
|
55648
55809
|
if (!assistantNode.length) {
|
|
55649
55810
|
assistantNode = thumb.closest(this.findSelector(TURN_CONTAINER))
|
|
55650
55811
|
.find(assistantSelector);
|
|
@@ -55652,15 +55813,15 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55652
55813
|
this.emit('user_reaction', {
|
|
55653
55814
|
agentId: this.id,
|
|
55654
55815
|
messageId: this.getMessageId(assistantNode),
|
|
55655
|
-
content
|
|
55816
|
+
content
|
|
55656
55817
|
});
|
|
55657
|
-
}
|
|
55818
|
+
}
|
|
55658
55819
|
// On a new M365 conversation the browser does a full page reload to the
|
|
55659
55820
|
// conversation URL. the old page sets FRESH_CONVERSATION_KEY when streaming starts
|
|
55660
55821
|
// without a conversation id; the new page picks it up here and triggers onSubmissionEnd
|
|
55661
55822
|
// to scan the already-rendered messages.
|
|
55662
|
-
|
|
55663
|
-
|
|
55823
|
+
tryFlushNewConversation() {
|
|
55824
|
+
const ts = +this.api.sessionStorage.getItem(NEW_CONVERSATION_KEY);
|
|
55664
55825
|
if (!ts)
|
|
55665
55826
|
return;
|
|
55666
55827
|
this.api.sessionStorage.removeItem(NEW_CONVERSATION_KEY);
|
|
@@ -55669,14 +55830,14 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55669
55830
|
if (!this.getConversationId())
|
|
55670
55831
|
return;
|
|
55671
55832
|
this.startStreamingEndTimer();
|
|
55672
|
-
}
|
|
55833
|
+
}
|
|
55673
55834
|
// observe the streaming indicator
|
|
55674
|
-
|
|
55835
|
+
setupStreamingObserver() {
|
|
55675
55836
|
this.wasStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
55676
55837
|
this.stopStreamingEndTimer();
|
|
55677
|
-
|
|
55678
|
-
|
|
55679
|
-
|
|
55838
|
+
const MutationObserver = getZoneSafeMethod(this._, 'MutationObserver');
|
|
55839
|
+
const observer = new MutationObserver(this.handleMutation.bind(this));
|
|
55840
|
+
const attrName = this.findSelector(STREAMING_ACTIVE_ATTR);
|
|
55680
55841
|
observer.observe(this.root, {
|
|
55681
55842
|
childList: true,
|
|
55682
55843
|
subtree: true,
|
|
@@ -55684,7 +55845,7 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55684
55845
|
attributeFilter: attrName ? [attrName] : undefined
|
|
55685
55846
|
});
|
|
55686
55847
|
this.observers.push(observer);
|
|
55687
|
-
}
|
|
55848
|
+
}
|
|
55688
55849
|
// look for changes in the state of the streaming indicator.
|
|
55689
55850
|
// streaming started -> a prompt has been submitted
|
|
55690
55851
|
// streaming ended -> got a response
|
|
@@ -55693,8 +55854,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55693
55854
|
// we don't send the agent_response immediately when the streaming indicator is cleared
|
|
55694
55855
|
// because it clears slightly before the final text chunk is committed to the DOM so the
|
|
55695
55856
|
// end-handling is deferred by a short settle window
|
|
55696
|
-
|
|
55697
|
-
|
|
55857
|
+
handleMutation() {
|
|
55858
|
+
const isStreaming = this.select(STREAMING_ACTIVE).length > 0;
|
|
55698
55859
|
if (isStreaming === this.wasStreaming)
|
|
55699
55860
|
return;
|
|
55700
55861
|
if (isStreaming) { // started streaming
|
|
@@ -55717,9 +55878,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55717
55878
|
this.startStreamingEndTimer();
|
|
55718
55879
|
}
|
|
55719
55880
|
this.wasStreaming = isStreaming;
|
|
55720
|
-
}
|
|
55721
|
-
|
|
55722
|
-
if (attempt === void 0) { attempt = 1; }
|
|
55881
|
+
}
|
|
55882
|
+
onSubmissionStart(attempt = 1) {
|
|
55723
55883
|
this.requestNode = this.findLastRequestNode();
|
|
55724
55884
|
if (this.requestNode) {
|
|
55725
55885
|
this.handleUserMessage(this.requestNode);
|
|
@@ -55730,13 +55890,13 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55730
55890
|
if (attempt < SUBMISSION_START_MAX_ATTEMPTS) {
|
|
55731
55891
|
this.startSubmissionStartRetryTimer(attempt + 1);
|
|
55732
55892
|
}
|
|
55733
|
-
}
|
|
55734
|
-
|
|
55893
|
+
}
|
|
55894
|
+
onSubmissionEnd() {
|
|
55735
55895
|
this.stopSubmissionStartRetryTimer();
|
|
55736
55896
|
if (this.getConversationId()) {
|
|
55737
55897
|
this.api.sessionStorage.removeItem(NEW_CONVERSATION_KEY);
|
|
55738
55898
|
}
|
|
55739
|
-
|
|
55899
|
+
let requestNode = this.requestNode;
|
|
55740
55900
|
this.requestNode = null;
|
|
55741
55901
|
if (!requestNode) {
|
|
55742
55902
|
// onSubmissionStart didn't send, send it now
|
|
@@ -55745,26 +55905,26 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55745
55905
|
return;
|
|
55746
55906
|
this.handleUserMessage(requestNode);
|
|
55747
55907
|
}
|
|
55748
|
-
|
|
55908
|
+
const requestEl = requestNode[0];
|
|
55749
55909
|
if (!requestEl)
|
|
55750
55910
|
return;
|
|
55751
55911
|
// the request is the latest user message, so any assistant message that
|
|
55752
55912
|
// follows it in the DOM is a response to it. document order is already
|
|
55753
55913
|
// chronological, so we emit as we go
|
|
55754
|
-
|
|
55755
|
-
for (
|
|
55756
|
-
|
|
55914
|
+
const assistantNodes = this.select(ASSISTANT_MESSAGE);
|
|
55915
|
+
for (let i = 0; i < assistantNodes.length; i++) {
|
|
55916
|
+
const el = assistantNodes[i];
|
|
55757
55917
|
if (requestEl.compareDocumentPosition(el) & Node.DOCUMENT_POSITION_FOLLOWING) {
|
|
55758
55918
|
this.handleAssistantMessage(this.dom(el));
|
|
55759
55919
|
}
|
|
55760
55920
|
}
|
|
55761
|
-
}
|
|
55762
|
-
|
|
55763
|
-
|
|
55921
|
+
}
|
|
55922
|
+
extractContent(node) {
|
|
55923
|
+
let source = node;
|
|
55764
55924
|
// optional: content inside a descendant
|
|
55765
|
-
|
|
55925
|
+
const contentSelector = this.findSelector(MESSAGE_CONTENT);
|
|
55766
55926
|
if (contentSelector) {
|
|
55767
|
-
|
|
55927
|
+
const contentNode = node.find(contentSelector);
|
|
55768
55928
|
if (contentNode.length) {
|
|
55769
55929
|
source = contentNode;
|
|
55770
55930
|
}
|
|
@@ -55772,59 +55932,59 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55772
55932
|
// .text() reads innerText, which is empty for content-visibility:auto / off-screen subtrees
|
|
55773
55933
|
// (e.g. claude.ai's scrolled-up messages). Keep innerText as the primary source so agents
|
|
55774
55934
|
// whose content already works are unchanged, and fall back to textContent only when it's empty.
|
|
55775
|
-
|
|
55935
|
+
const primary = source.text().trim();
|
|
55776
55936
|
if (primary)
|
|
55777
55937
|
return primary;
|
|
55778
55938
|
return source[0].textContent.trim();
|
|
55779
|
-
}
|
|
55780
|
-
|
|
55781
|
-
|
|
55939
|
+
}
|
|
55940
|
+
getMessageId(node) {
|
|
55941
|
+
const attr = this.findSelector(MESSAGE_ID_ATTR);
|
|
55782
55942
|
if (!attr) {
|
|
55783
55943
|
return this.syntheticMessageId(node[0]);
|
|
55784
55944
|
}
|
|
55785
55945
|
return node.attr(attr);
|
|
55786
|
-
}
|
|
55946
|
+
}
|
|
55787
55947
|
// Agents with no DOM message id (e.g. claude.ai) get a synthetic id based on the role and
|
|
55788
55948
|
// position in document order.
|
|
55789
|
-
|
|
55949
|
+
syntheticMessageId(el) {
|
|
55790
55950
|
if (!el)
|
|
55791
55951
|
return undefined;
|
|
55792
|
-
|
|
55793
|
-
|
|
55794
|
-
|
|
55795
|
-
|
|
55796
|
-
for (
|
|
55952
|
+
const userSelector = this.findSelector(USER_MESSAGE);
|
|
55953
|
+
const isUser = userSelector && this.Sizzle.matchesSelector(el, userSelector);
|
|
55954
|
+
const role = isUser ? 'u' : 'a';
|
|
55955
|
+
const siblings = this.select(isUser ? USER_MESSAGE : ASSISTANT_MESSAGE);
|
|
55956
|
+
for (let i = 0; i < siblings.length; i++) {
|
|
55797
55957
|
if (siblings[i] === el) {
|
|
55798
|
-
return
|
|
55958
|
+
return `${role}-${i}`;
|
|
55799
55959
|
}
|
|
55800
55960
|
}
|
|
55801
55961
|
return undefined; // el isn't among the rendered messages — no meaningful index
|
|
55802
|
-
}
|
|
55803
|
-
|
|
55962
|
+
}
|
|
55963
|
+
handleUserMessage(node) {
|
|
55804
55964
|
this.emit('prompt', {
|
|
55805
55965
|
agentId: this.id,
|
|
55806
55966
|
messageId: this.getMessageId(node),
|
|
55807
55967
|
content: this.extractContent(node)
|
|
55808
55968
|
});
|
|
55809
|
-
}
|
|
55810
|
-
|
|
55811
|
-
|
|
55812
|
-
|
|
55969
|
+
}
|
|
55970
|
+
handleAssistantMessage(node) {
|
|
55971
|
+
const modelUsedAttr = this.findSelector(MODEL_USED_ATTR);
|
|
55972
|
+
const modelUsed = modelUsedAttr && node.attr(modelUsedAttr);
|
|
55813
55973
|
this.emit('agent_response', {
|
|
55814
55974
|
agentId: this.id,
|
|
55815
55975
|
messageId: this.getMessageId(node),
|
|
55816
55976
|
agentModelsUsed: modelUsed ? [modelUsed] : [],
|
|
55817
55977
|
content: this.extractContent(node)
|
|
55818
55978
|
});
|
|
55819
|
-
}
|
|
55820
|
-
|
|
55979
|
+
}
|
|
55980
|
+
findLastRequestNode() {
|
|
55821
55981
|
if (!this.getConversationId())
|
|
55822
55982
|
return null;
|
|
55823
|
-
|
|
55983
|
+
const node = this._.last(this.select(USER_MESSAGE));
|
|
55824
55984
|
if (!node)
|
|
55825
55985
|
return null;
|
|
55826
|
-
|
|
55827
|
-
|
|
55986
|
+
const $node = this.dom(node);
|
|
55987
|
+
const messageId = this.getMessageId($node);
|
|
55828
55988
|
if (!messageId)
|
|
55829
55989
|
return null;
|
|
55830
55990
|
// the node may still be rendering (e.g. a framework interpolating an
|
|
@@ -55836,99 +55996,97 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55836
55996
|
return null;
|
|
55837
55997
|
this.lastReturnedMessageId = messageId;
|
|
55838
55998
|
return $node;
|
|
55839
|
-
}
|
|
55840
|
-
|
|
55999
|
+
}
|
|
56000
|
+
findSelector(type) {
|
|
55841
56001
|
return this.selectors[type];
|
|
55842
|
-
}
|
|
55843
|
-
|
|
56002
|
+
}
|
|
56003
|
+
select(type) {
|
|
55844
56004
|
return this.dom(this.findSelector(type), this.root);
|
|
55845
|
-
}
|
|
55846
|
-
|
|
55847
|
-
|
|
56005
|
+
}
|
|
56006
|
+
getConversationId() {
|
|
56007
|
+
const m = location.href.match(this.conversationIdRegex);
|
|
55848
56008
|
if (!m)
|
|
55849
56009
|
return null;
|
|
55850
56010
|
return m[1] !== undefined ? m[1] : m[0];
|
|
55851
|
-
}
|
|
55852
|
-
|
|
56011
|
+
}
|
|
56012
|
+
getCustomAgentId() {
|
|
55853
56013
|
if (!this.customAgentIdRegex)
|
|
55854
56014
|
return undefined;
|
|
55855
56015
|
// The id may live in the page URL (e.g. gemini /gem/<id>) or,
|
|
55856
56016
|
// when customAgentId is set, in the href of a DOM element
|
|
55857
|
-
|
|
56017
|
+
let source = location.href;
|
|
55858
56018
|
if (this.findSelector(CUSTOM_AGENT_ID)) {
|
|
55859
|
-
|
|
56019
|
+
const node = this.select(CUSTOM_AGENT_ID);
|
|
55860
56020
|
if (!node.length)
|
|
55861
56021
|
return undefined;
|
|
55862
56022
|
source = node.attr('href') || '';
|
|
55863
56023
|
}
|
|
55864
|
-
|
|
56024
|
+
const m = source.match(this.customAgentIdRegex);
|
|
55865
56025
|
if (!m)
|
|
55866
56026
|
return undefined;
|
|
55867
56027
|
return m[1] !== undefined ? m[1] : m[0];
|
|
55868
|
-
}
|
|
55869
|
-
|
|
56028
|
+
}
|
|
56029
|
+
getCustomAgentName() {
|
|
55870
56030
|
if (!this.findSelector(CUSTOM_AGENT_NAME))
|
|
55871
56031
|
return '';
|
|
55872
|
-
|
|
56032
|
+
const node = this.select(CUSTOM_AGENT_NAME);
|
|
55873
56033
|
if (!node.length)
|
|
55874
56034
|
return '';
|
|
55875
56035
|
return node.text().trim();
|
|
55876
|
-
}
|
|
55877
|
-
|
|
55878
|
-
|
|
56036
|
+
}
|
|
56037
|
+
addCustomAgentInfo(eventPayload) {
|
|
56038
|
+
const customAgentId = this.getCustomAgentId();
|
|
55879
56039
|
if (!customAgentId)
|
|
55880
56040
|
return;
|
|
55881
56041
|
eventPayload.customAgentId = customAgentId;
|
|
55882
|
-
|
|
56042
|
+
const customAgentName = this.getCustomAgentName();
|
|
55883
56043
|
if (customAgentName) {
|
|
55884
56044
|
eventPayload.customAgentName = customAgentName;
|
|
55885
56045
|
}
|
|
55886
|
-
}
|
|
55887
|
-
|
|
56046
|
+
}
|
|
56047
|
+
onSubmit(callback) {
|
|
55888
56048
|
this.listeners.push(callback);
|
|
55889
|
-
}
|
|
55890
|
-
|
|
56049
|
+
}
|
|
56050
|
+
emit(eventType, eventPayload) {
|
|
55891
56051
|
eventPayload.conversationId = this.getConversationId();
|
|
55892
56052
|
this.addCustomAgentInfo(eventPayload);
|
|
55893
|
-
this._.each(this.listeners,
|
|
55894
|
-
}
|
|
55895
|
-
|
|
55896
|
-
var _this = this;
|
|
56053
|
+
this._.each(this.listeners, (cb) => cb(eventType, eventPayload));
|
|
56054
|
+
}
|
|
56055
|
+
startStreamingEndTimer() {
|
|
55897
56056
|
this.stopStreamingEndTimer();
|
|
55898
|
-
this.streamingEndTimer = setTimeout$1(
|
|
55899
|
-
|
|
55900
|
-
|
|
56057
|
+
this.streamingEndTimer = setTimeout$1(() => {
|
|
56058
|
+
this.streamingEndTimer = null;
|
|
56059
|
+
this.onSubmissionEnd();
|
|
55901
56060
|
}, STREAMING_END_SETTLE_MS);
|
|
55902
|
-
}
|
|
55903
|
-
|
|
56061
|
+
}
|
|
56062
|
+
stopStreamingEndTimer() {
|
|
55904
56063
|
if (!this.streamingEndTimer)
|
|
55905
56064
|
return;
|
|
55906
56065
|
clearTimeout(this.streamingEndTimer);
|
|
55907
56066
|
this.streamingEndTimer = null;
|
|
55908
|
-
}
|
|
55909
|
-
|
|
55910
|
-
var _this = this;
|
|
56067
|
+
}
|
|
56068
|
+
startSubmissionStartRetryTimer(attempt) {
|
|
55911
56069
|
this.stopSubmissionStartRetryTimer();
|
|
55912
|
-
this.submissionStartRetryTimer = setTimeout$1(
|
|
55913
|
-
|
|
55914
|
-
|
|
56070
|
+
this.submissionStartRetryTimer = setTimeout$1(() => {
|
|
56071
|
+
this.submissionStartRetryTimer = null;
|
|
56072
|
+
this.onSubmissionStart(attempt);
|
|
55915
56073
|
}, SUBMISSION_START_RETRY_MS);
|
|
55916
|
-
}
|
|
55917
|
-
|
|
56074
|
+
}
|
|
56075
|
+
stopSubmissionStartRetryTimer() {
|
|
55918
56076
|
if (!this.submissionStartRetryTimer)
|
|
55919
56077
|
return;
|
|
55920
56078
|
clearTimeout(this.submissionStartRetryTimer);
|
|
55921
56079
|
this.submissionStartRetryTimer = null;
|
|
55922
|
-
}
|
|
55923
|
-
|
|
56080
|
+
}
|
|
56081
|
+
suspend() {
|
|
55924
56082
|
this.isActive = false;
|
|
55925
|
-
}
|
|
55926
|
-
|
|
56083
|
+
}
|
|
56084
|
+
resume() {
|
|
55927
56085
|
this.isActive = true;
|
|
55928
56086
|
this.tryFlushNewConversation();
|
|
55929
|
-
}
|
|
55930
|
-
|
|
55931
|
-
this._.each(this.observers,
|
|
56087
|
+
}
|
|
56088
|
+
teardown() {
|
|
56089
|
+
this._.each(this.observers, (o) => o && o.disconnect && o.disconnect());
|
|
55932
56090
|
this.observers = [];
|
|
55933
56091
|
if (this.reactionClickHandler && this.root) {
|
|
55934
56092
|
this.root.removeEventListener('click', this.reactionClickHandler, true);
|
|
@@ -55937,9 +56095,8 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55937
56095
|
this.stopStreamingEndTimer();
|
|
55938
56096
|
this.stopSubmissionStartRetryTimer();
|
|
55939
56097
|
this.listeners = [];
|
|
55940
|
-
}
|
|
55941
|
-
|
|
55942
|
-
}());
|
|
56098
|
+
}
|
|
56099
|
+
}
|
|
55943
56100
|
|
|
55944
56101
|
/*
|
|
55945
56102
|
* Conversation Analytics Plugin
|
|
@@ -55949,21 +56106,21 @@ var DOMConversation = /** @class */ (function () {
|
|
|
55949
56106
|
* The sibling built-in PromptAnalytics plugin owns the network + DOMPrompt AI-agents
|
|
55950
56107
|
*/
|
|
55951
56108
|
function ConversationAnalytics() {
|
|
55952
|
-
|
|
55953
|
-
|
|
55954
|
-
|
|
55955
|
-
|
|
55956
|
-
|
|
55957
|
-
|
|
55958
|
-
|
|
56109
|
+
let pendo;
|
|
56110
|
+
let api;
|
|
56111
|
+
let _;
|
|
56112
|
+
let log;
|
|
56113
|
+
let conversations = [];
|
|
56114
|
+
let agentsCache = new Map();
|
|
56115
|
+
const CONFIG_NAME = 'aiAgents';
|
|
55959
56116
|
return {
|
|
55960
56117
|
name: 'ConversationAnalytics',
|
|
55961
|
-
initialize
|
|
55962
|
-
teardown
|
|
55963
|
-
onConfigLoaded
|
|
55964
|
-
observeConversation
|
|
55965
|
-
sendConversationEvent
|
|
55966
|
-
reEvaluatePageRules
|
|
56118
|
+
initialize,
|
|
56119
|
+
teardown,
|
|
56120
|
+
onConfigLoaded,
|
|
56121
|
+
observeConversation,
|
|
56122
|
+
sendConversationEvent,
|
|
56123
|
+
reEvaluatePageRules
|
|
55967
56124
|
};
|
|
55968
56125
|
function initialize(pendoGlobal, PluginAPI) {
|
|
55969
56126
|
var _a;
|
|
@@ -55971,7 +56128,7 @@ function ConversationAnalytics() {
|
|
|
55971
56128
|
api = PluginAPI;
|
|
55972
56129
|
_ = pendo._;
|
|
55973
56130
|
log = api.log;
|
|
55974
|
-
|
|
56131
|
+
const { ConfigReader } = api;
|
|
55975
56132
|
ConfigReader.addOption(CONFIG_NAME, [
|
|
55976
56133
|
ConfigReader.sources.PENDO_CONFIG_SRC,
|
|
55977
56134
|
ConfigReader.sources.SNIPPET_SRC
|
|
@@ -55984,13 +56141,12 @@ function ConversationAnalytics() {
|
|
|
55984
56141
|
// Test if the current URL matches the page rule for an agent. The raw matcher lives in core
|
|
55985
56142
|
// and is reached through PluginAPI (independent plugins cannot import it directly); it falls
|
|
55986
56143
|
// back to the normalized URL internally when no URL is passed.
|
|
55987
|
-
function testPageRule(pageRule, agentId) {
|
|
55988
|
-
if (agentId === void 0) { agentId = 'unknown'; }
|
|
56144
|
+
function testPageRule(pageRule, agentId = 'unknown') {
|
|
55989
56145
|
// Convert //*/agent pattern to work with full URLs
|
|
55990
|
-
|
|
56146
|
+
let fixedPageRule = pageRule;
|
|
55991
56147
|
if (Array.isArray(pageRule)) {
|
|
55992
|
-
|
|
55993
|
-
fixedPageRule = _.map(validRules,
|
|
56148
|
+
const validRules = _.filter(pageRule, rule => rule && rule.trim() !== '');
|
|
56149
|
+
fixedPageRule = _.map(validRules, rule => rule.startsWith('//*/') ? rule.substring(1) : rule);
|
|
55994
56150
|
}
|
|
55995
56151
|
else if (typeof pageRule === 'string' && pageRule.startsWith('//*/')) {
|
|
55996
56152
|
fixedPageRule = pageRule.substring(1);
|
|
@@ -56002,9 +56158,9 @@ function ConversationAnalytics() {
|
|
|
56002
56158
|
});
|
|
56003
56159
|
}
|
|
56004
56160
|
function reEvaluatePageRules() {
|
|
56005
|
-
_.each(conversations,
|
|
56006
|
-
|
|
56007
|
-
|
|
56161
|
+
_.each(conversations, conversation => {
|
|
56162
|
+
const agent = findAgentById(conversation.id);
|
|
56163
|
+
const shouldBeActive = agent && testPageRule(agent.pageRule, agent.id);
|
|
56008
56164
|
if (shouldBeActive) {
|
|
56009
56165
|
conversation.resume();
|
|
56010
56166
|
}
|
|
@@ -56012,14 +56168,14 @@ function ConversationAnalytics() {
|
|
|
56012
56168
|
conversation.suspend();
|
|
56013
56169
|
}
|
|
56014
56170
|
});
|
|
56015
|
-
|
|
56016
|
-
|
|
56017
|
-
_.each(allAgents,
|
|
56171
|
+
const currentlyActiveIds = _.map(_.filter(conversations, conversation => conversation.isActive), conversation => conversation.id);
|
|
56172
|
+
const allAgents = api.ConfigReader.get(CONFIG_NAME) || [];
|
|
56173
|
+
_.each(allAgents, aiAgent => {
|
|
56018
56174
|
if (!isConversationAgent(aiAgent)) {
|
|
56019
56175
|
return;
|
|
56020
56176
|
}
|
|
56021
|
-
|
|
56022
|
-
|
|
56177
|
+
const isCurrentlyActive = _.contains(currentlyActiveIds, aiAgent.id);
|
|
56178
|
+
const shouldBeActive = testPageRule(aiAgent.pageRule, aiAgent.id);
|
|
56023
56179
|
if (shouldBeActive && !isCurrentlyActive) {
|
|
56024
56180
|
observeConversation(aiAgent);
|
|
56025
56181
|
}
|
|
@@ -56033,13 +56189,12 @@ function ConversationAnalytics() {
|
|
|
56033
56189
|
function isConversationAgent(agent) {
|
|
56034
56190
|
return DOMConversation.supportedPreset(agent.preset);
|
|
56035
56191
|
}
|
|
56036
|
-
function onConfigLoaded(aiAgents) {
|
|
56037
|
-
if (aiAgents === void 0) { aiAgents = []; }
|
|
56192
|
+
function onConfigLoaded(aiAgents = []) {
|
|
56038
56193
|
if (!aiAgents || !_.isArray(aiAgents) || aiAgents.length === 0) {
|
|
56039
56194
|
return;
|
|
56040
56195
|
}
|
|
56041
56196
|
agentsCache.clear();
|
|
56042
|
-
_.each(aiAgents,
|
|
56197
|
+
_.each(aiAgents, aiAgent => {
|
|
56043
56198
|
if (!isConversationAgent(aiAgent)) {
|
|
56044
56199
|
return;
|
|
56045
56200
|
}
|
|
@@ -56050,24 +56205,24 @@ function ConversationAnalytics() {
|
|
|
56050
56205
|
});
|
|
56051
56206
|
}
|
|
56052
56207
|
function observeConversation(config) {
|
|
56053
|
-
|
|
56208
|
+
const { id, cssSelectors } = config;
|
|
56054
56209
|
// Check if this agent is already being tracked
|
|
56055
|
-
|
|
56210
|
+
const existing = _.find(conversations, conversation => conversation.id === id);
|
|
56056
56211
|
if (existing) {
|
|
56057
56212
|
return;
|
|
56058
56213
|
}
|
|
56059
|
-
|
|
56214
|
+
const missing = DOMConversation.validateConfig(cssSelectors);
|
|
56060
56215
|
if (missing.length) {
|
|
56061
|
-
log.error('aiAgent config missing required selectors', { agentId: id, missing
|
|
56216
|
+
log.error('aiAgent config missing required selectors', { agentId: id, missing });
|
|
56062
56217
|
return;
|
|
56063
56218
|
}
|
|
56064
|
-
|
|
56219
|
+
const conversation = new DOMConversation(pendo, api, id, cssSelectors);
|
|
56065
56220
|
conversation.onSubmit(sendConversationEvent);
|
|
56066
56221
|
conversations.push(conversation);
|
|
56067
56222
|
}
|
|
56068
56223
|
function sendConversationEvent(eventType, eventPayload) {
|
|
56069
56224
|
// Block event if the conversation is suspended
|
|
56070
|
-
|
|
56225
|
+
const conversation = _.find(conversations, c => c.id === eventPayload.agentId);
|
|
56071
56226
|
if (conversation && !conversation.isActive) {
|
|
56072
56227
|
return;
|
|
56073
56228
|
}
|
|
@@ -56075,7 +56230,7 @@ function ConversationAnalytics() {
|
|
|
56075
56230
|
api.analytics.collectEvent(eventType, eventPayload, undefined, 'agentic');
|
|
56076
56231
|
}
|
|
56077
56232
|
function teardown() {
|
|
56078
|
-
_.each(conversations,
|
|
56233
|
+
_.each(conversations, conversation => conversation.teardown());
|
|
56079
56234
|
conversations = [];
|
|
56080
56235
|
agentsCache.clear();
|
|
56081
56236
|
}
|