@pendo/agent 2.315.1 → 2.316.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.
@@ -2891,6 +2891,17 @@ var ConfigReader = (function () {
2891
2891
  */
2892
2892
  addOption('dataHost', [SNIPPET_SRC, PENDO_CONFIG_SRC]);
2893
2893
  addOption('disableAutoInitialize');
2894
+ /**
2895
+ * If set to `true` the web SDK will wait for the host application to be both loaded and visible before
2896
+ * starting the initialization process.
2897
+ *
2898
+ * @access public
2899
+ * @category Config/Core
2900
+ * @name initializeWhenVisible
2901
+ * @default false
2902
+ * @type {boolean}
2903
+ */
2904
+ addOption('initializeWhenVisible', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
2894
2905
  /**
2895
2906
  * Although the name refers to cookies, if set to `true` the web SDK will not persist any data in local
2896
2907
  * storage or cookies and will rely only on memory.
@@ -3945,8 +3956,8 @@ let SERVER = '';
3945
3956
  let ASSET_HOST = '';
3946
3957
  let ASSET_PATH = '';
3947
3958
  let DESIGNER_SERVER = '';
3948
- let VERSION = '2.315.1_';
3949
- let PACKAGE_VERSION = '2.315.1';
3959
+ let VERSION = '2.316.0_';
3960
+ let PACKAGE_VERSION = '2.316.0';
3950
3961
  let LOADER = 'xhr';
3951
3962
  /* eslint-enable web-sdk-eslint-rules/no-gulp-env-references */
3952
3963
  /**
@@ -11866,13 +11877,10 @@ var messageValidator = function (msg) {
11866
11877
  var data = typeof msg.data === 'string' ? JSON.parse(msg.data) : msg.data;
11867
11878
  var origin = msg.origin;
11868
11879
  var source = msg.source;
11869
- if (data.action || data.mutation) {
11870
- return; // Ignore action messages
11871
- }
11872
- if (!data.type || typeof data.type !== 'string') {
11873
- log.debug('Invalid Message: Missing \'type\' in data format');
11880
+ if (data.action || data.mutation)
11881
+ return;
11882
+ if (!data.type || typeof data.type !== 'string')
11874
11883
  return;
11875
- }
11876
11884
  return { data, origin, source };
11877
11885
  }
11878
11886
  catch (e) {
@@ -14098,6 +14106,22 @@ var whenLoadedCall = function (callback, win) {
14098
14106
  }
14099
14107
  return _.noop;
14100
14108
  };
14109
+ const whenVisibleCall = (callback, win = window) => {
14110
+ const { document } = win;
14111
+ const waitForVis = ConfigReader.get('initializeWhenVisible', false);
14112
+ if (!waitForVis || document.visibilityState === 'visible') {
14113
+ callback();
14114
+ return _.noop;
14115
+ }
14116
+ const stopVisListener = attachEventInternal(document, 'visibilitychange', () => {
14117
+ if (document.visibilityState === 'visible') {
14118
+ callback();
14119
+ // need to shut this down immediately as visibility can continue to change
14120
+ stopVisListener();
14121
+ }
14122
+ });
14123
+ return stopVisListener;
14124
+ };
14101
14125
 
14102
14126
  /**
14103
14127
  * Returns the normalized URL sent from the backend. This won't always
@@ -28161,6 +28185,344 @@ var GuideActivity = (function () {
28161
28185
  }
28162
28186
  })();
28163
28187
 
28188
+ function arrayEquals(array1, array2) {
28189
+ if (array1.length != array2.length)
28190
+ return false;
28191
+ return _.all(array1, function (item, i) {
28192
+ return item === array2[i];
28193
+ });
28194
+ }
28195
+ class DOMActivationPhase {
28196
+ constructor(DOMActivation) {
28197
+ this.maxTargets = 50;
28198
+ this.domActivation = DOMActivation;
28199
+ this.name = 'dom';
28200
+ this.queue = [];
28201
+ }
28202
+ markDirty() {
28203
+ this.queue.push.apply(this.queue, this.domActivation.guides);
28204
+ }
28205
+ process(monitor) {
28206
+ var domActivationGuide = this.queue.shift();
28207
+ if (!domActivationGuide)
28208
+ return;
28209
+ monitor.saveContext(domActivationGuide);
28210
+ var targets;
28211
+ try {
28212
+ targets = SizzleProxy(domActivationGuide.selector);
28213
+ }
28214
+ catch (e) {
28215
+ targets = [];
28216
+ }
28217
+ if (targets.length > this.maxTargets) {
28218
+ targets.length = this.maxTargets;
28219
+ }
28220
+ if (!arrayEquals(targets, domActivationGuide.targets)) {
28221
+ domActivationGuide.targets = targets;
28222
+ this.domActivation.detach(domActivationGuide, this.domActivation.targets);
28223
+ _.each(targets, function (target) {
28224
+ this.domActivation.attach(target, domActivationGuide, this.domActivation.targets);
28225
+ }, this);
28226
+ }
28227
+ }
28228
+ handleProcessTimeExceeded(monitor) {
28229
+ const ctx = monitor.getContext();
28230
+ if (ctx) {
28231
+ log.warn('Element activated guide (' + ctx.id + ') timeout exceeded');
28232
+ }
28233
+ }
28234
+ cancel() {
28235
+ this.queue.length = 0;
28236
+ }
28237
+ isComplete() {
28238
+ return !this.queue.length;
28239
+ }
28240
+ }
28241
+ var DOMActivation = (function () {
28242
+ var keyAttr = 'pendoTargetId';
28243
+ var pluginApi;
28244
+ /*
28245
+ domActivatedGuides = [
28246
+ {
28247
+ id: 'aGuideId',
28248
+ events: ['click', 'mouseover'],
28249
+ selector: '.selector .for .target',
28250
+ targets: [array, of, dom, references]
28251
+ }
28252
+ ]
28253
+ */
28254
+ var domActivatedGuides = [];
28255
+ /*
28256
+ activationTargets = {
28257
+ aGuideId: 'aTargetId',
28258
+ aTargetId: {
28259
+ target: {{referenceToDomElement}},
28260
+ events: {
28261
+ click: {
28262
+ guideIds: {
28263
+ aGuideId: 1,
28264
+ anotherGuideId: 1
28265
+ },
28266
+ fn: {{partial(eventHandler, guideIds)}}
28267
+ },
28268
+ mouseover: {{same format as click}}
28269
+ }
28270
+ }
28271
+ {{more guide and target ids...}}
28272
+ }
28273
+ */
28274
+ var activationTargets = {};
28275
+ var domPhase;
28276
+ return {
28277
+ name: 'DOMActivation',
28278
+ key: keyAttr,
28279
+ guides: domActivatedGuides,
28280
+ targets: activationTargets,
28281
+ reset,
28282
+ init,
28283
+ attach: attachGuideToTarget,
28284
+ detach: detachGuideFromTarget,
28285
+ handler: eventHandler,
28286
+ activates,
28287
+ prefetch,
28288
+ initialize,
28289
+ teardown
28290
+ };
28291
+ function initialize(pendo, PluginAPI) {
28292
+ pluginApi = PluginAPI;
28293
+ PluginAPI.Events.on('deliverablesLoaded', reset);
28294
+ PluginAPI.Events.on('guideListChanged', handleGuideListChanged);
28295
+ PluginAPI.Events.on('guidesLoaded', handleGuidesLoaded);
28296
+ domPhase = new DOMActivationPhase(DOMActivation);
28297
+ addUpdatePhase(domPhase);
28298
+ }
28299
+ function teardown() {
28300
+ removeUpdatePhase(domPhase);
28301
+ pluginApi.Events.off('deliverablesLoaded', reset);
28302
+ pluginApi.Events.off('guideListChanged', handleGuideListChanged);
28303
+ pluginApi.Events.off('guidesLoaded', handleGuidesLoaded);
28304
+ }
28305
+ function handleGuideListChanged() {
28306
+ reset();
28307
+ init(getLocalActiveGuides());
28308
+ }
28309
+ function handleGuidesLoaded() {
28310
+ prefetch(getLocalActiveGuides());
28311
+ }
28312
+ function attachGuideToTarget(target, domActivationGuide, activationTargets) {
28313
+ var targetKey = target[keyAttr];
28314
+ var handler = targetKey ? activationTargets[targetKey] : null;
28315
+ if (!handler) {
28316
+ targetKey = targetKey || 'target' + _.uniqueId();
28317
+ handler = {
28318
+ target,
28319
+ events: {}
28320
+ };
28321
+ activationTargets[targetKey] = handler;
28322
+ target[keyAttr] = targetKey;
28323
+ }
28324
+ var targetList = activationTargets[domActivationGuide.id] || [];
28325
+ targetList.push(targetKey);
28326
+ activationTargets[domActivationGuide.id] = targetList;
28327
+ _.each(domActivationGuide.events, function (eventType) {
28328
+ var eventTypeHandler = handler.events[eventType];
28329
+ if (!eventTypeHandler) {
28330
+ eventTypeHandler = {
28331
+ guideIds: {}
28332
+ };
28333
+ eventTypeHandler.fn = _.partial(eventHandler, _, eventTypeHandler.guideIds);
28334
+ if (eventType === 'mouseover') {
28335
+ eventType = 'mouseenter';
28336
+ }
28337
+ attachEvent(target, eventType, eventTypeHandler.fn);
28338
+ handler.events[eventType] = eventTypeHandler;
28339
+ }
28340
+ eventTypeHandler.guideIds[domActivationGuide.id] = 1;
28341
+ });
28342
+ }
28343
+ function detachGuideFromTarget(domActivationGuide, activationTargets) {
28344
+ _.each(activationTargets[domActivationGuide.id], function (targetKey) {
28345
+ var handler = targetKey ? activationTargets[targetKey] : null;
28346
+ if (handler) {
28347
+ _.each(handler.events, function (eventTypeHandler, eventType) {
28348
+ if (eventTypeHandler && eventTypeHandler.guideIds) {
28349
+ delete eventTypeHandler.guideIds[domActivationGuide.id];
28350
+ if (_.size(eventTypeHandler.guideIds) <= 0) {
28351
+ if (eventType === 'mouseover') {
28352
+ eventType = 'mouseenter';
28353
+ }
28354
+ detachEvent(handler.target, eventType, eventTypeHandler.fn);
28355
+ delete handler.events[eventType];
28356
+ }
28357
+ }
28358
+ });
28359
+ if (_.size(handler.events) <= 0) {
28360
+ delete handler.target[keyAttr];
28361
+ handler.target = null;
28362
+ delete activationTargets[targetKey];
28363
+ }
28364
+ }
28365
+ });
28366
+ delete activationTargets[domActivationGuide.id];
28367
+ }
28368
+ function eventHandler(e, guideIds) {
28369
+ if (e.pendoActivatedGuide || dom.data.get(e, 'advanced')) {
28370
+ return;
28371
+ }
28372
+ var prioritizeAdoptGuides = ConfigReader.get('adoptPrioritizeAdoptGuides');
28373
+ var guides = _.compact(_.map(_.keys(guideIds), function (id) {
28374
+ return findGuideById(id);
28375
+ }));
28376
+ guides = _.filter(guides, function (guide) {
28377
+ if (!guide.steps || !guide.steps.length) {
28378
+ return false;
28379
+ }
28380
+ if (_.get(guide, 'attributes.dom.isOnlyShowOnce')) {
28381
+ return !guide.steps[0].hasBeenSeen();
28382
+ }
28383
+ return true;
28384
+ });
28385
+ guides = _(guides).chain()
28386
+ .sortBy(function (guide) {
28387
+ return guide.state === 'staged' ? 0 : 1;
28388
+ })
28389
+ .sortBy(function (guide) {
28390
+ var isAdoptGuide = guide.isTraining;
28391
+ if (prioritizeAdoptGuides) {
28392
+ return isAdoptGuide ? 0 : 1;
28393
+ }
28394
+ return isAdoptGuide ? 1 : 0;
28395
+ })
28396
+ .value();
28397
+ var activatedGuide = _.find(guides, function (guide) {
28398
+ var firstStep = _.first(guide.steps);
28399
+ var isResourceCenter = _.get(guide, 'attributes.resourceCenter', false);
28400
+ if (isResourceCenter && guide.isShown()) {
28401
+ return BuildingBlockResourceCenter.dismissResourceCenter();
28402
+ }
28403
+ if (!firstStep.canShow())
28404
+ return false;
28405
+ if (guide.isShown())
28406
+ return true;
28407
+ return showGuide(firstStep, 'dom');
28408
+ });
28409
+ if (activatedGuide) {
28410
+ e.pendoActivatedGuide = activatedGuide.id;
28411
+ }
28412
+ }
28413
+ function reset() {
28414
+ _.each(domActivatedGuides, function (domActivationGuide) {
28415
+ detachGuideFromTarget(domActivationGuide, activationTargets);
28416
+ domActivationGuide.targets = [];
28417
+ });
28418
+ domActivatedGuides.length = 0;
28419
+ }
28420
+ function activates(guide) {
28421
+ if (!guide.id || !guide.steps || !guide.steps.length || !guide.hasLaunchMethod('dom'))
28422
+ return;
28423
+ if (!guide.steps[0].canShowOnPage(getNormalizedUrl()))
28424
+ return;
28425
+ var events = _.get(guide, 'attributes.activation.event', []);
28426
+ if (!events || !events.length)
28427
+ return;
28428
+ var selector = getActivationSelector(guide);
28429
+ if (!selector)
28430
+ return;
28431
+ return {
28432
+ id: guide.id,
28433
+ events,
28434
+ selector,
28435
+ targets: []
28436
+ };
28437
+ }
28438
+ function init(guideList) {
28439
+ _.each(guideList, function (guide) {
28440
+ var domActivatedGuide = activates(guide);
28441
+ if (domActivatedGuide) {
28442
+ domActivatedGuides.push(domActivatedGuide);
28443
+ }
28444
+ });
28445
+ }
28446
+ function prefetch(guides) {
28447
+ if (ConfigReader.get('disablePrefetch')) {
28448
+ return;
28449
+ }
28450
+ _.each(guides, function (guide) {
28451
+ if (!_.isFunction(guide.hasLaunchMethod) || !guide.hasLaunchMethod('dom'))
28452
+ return;
28453
+ if (!guide.steps || !guide.steps.length || !_.isFunction(guide.steps[0].fetchContent))
28454
+ return;
28455
+ guide.steps[0].fetchContent(true);
28456
+ });
28457
+ }
28458
+ })();
28459
+
28460
+ function AdvanceTrigger(element, method, step) {
28461
+ this.element = element;
28462
+ if (method == 'element') {
28463
+ this.method = 'click';
28464
+ }
28465
+ else if (method == 'hover') {
28466
+ this.method = 'mouseover';
28467
+ }
28468
+ else {
28469
+ this.method = method;
28470
+ }
28471
+ this.step = step;
28472
+ this.guide = step.getGuide();
28473
+ }
28474
+ AdvanceTrigger.prototype.add = function () {
28475
+ if (_.indexOf(this.guide.steps, this.step) === 0 && !AdvanceTrigger.shouldAttachHandler(this.guide, this.method))
28476
+ return;
28477
+ if (!isBadge(this.guide) || isWalkthrough(this.guide)) {
28478
+ this.setupElementEvent(this.element, this.method);
28479
+ }
28480
+ };
28481
+ AdvanceTrigger.prototype.remove = function () {
28482
+ this.teardownElementEvent(this.element, this.method);
28483
+ };
28484
+ // HTBD: (aka Here There Be Dragons)
28485
+ // Instead of detaching on hide, we're going to leave the
28486
+ // attach live until it's either advanced, dismissed or
28487
+ // re-rendered. The reason for this is it's too easy for
28488
+ // a race case to happen where the hide for this guide can
28489
+ // happen before the element click event happens and thus we
28490
+ // never get the onguideadvanced action being called.
28491
+ AdvanceTrigger.prototype.setupElementEvent = function (element, evt) {
28492
+ if (!this.advanceFn) {
28493
+ this.advanceFn = _.compose(_.bind(this.teardownElementEvent, this, element, evt), _.bind(this.step.advance, this.step));
28494
+ }
28495
+ AdvanceTrigger.attach(this.step, element, evt, this.advanceFn);
28496
+ };
28497
+ AdvanceTrigger.prototype.teardownElementEvent = function (element, evt) {
28498
+ log.info('detach onGuideAdvanced', { contexts: ['guide'] });
28499
+ detachEvent(element, evt, this.advanceFn, true);
28500
+ this.step.removeTrigger(this);
28501
+ };
28502
+ AdvanceTrigger.shouldAttachHandler = function shouldAttachHandler(guide, method) {
28503
+ return !guide.isActivatedByEvent(method) ||
28504
+ DOMActivation.activates(guide) ||
28505
+ (guide.attributes.activation.selector !== guide.steps[0].elementPathRule &&
28506
+ !!guide.attributes.activation.selector);
28507
+ };
28508
+ AdvanceTrigger.attach = function (step, element, evt, advanceFn) {
28509
+ if (!step)
28510
+ return;
28511
+ var handlers = AdvanceTrigger.handlers = AdvanceTrigger.handlers || {};
28512
+ var stepHandlers = handlers[step.id] = handlers[step.id] || [];
28513
+ for (var i = 0; i < stepHandlers.length; ++i) {
28514
+ var handler = stepHandlers[i];
28515
+ if (element === handler[0] && evt === handler[1]) {
28516
+ detachEvent(element, evt, handler[2], true);
28517
+ stepHandlers.splice(_.indexOf(stepHandlers, handler), 1);
28518
+ i--;
28519
+ }
28520
+ }
28521
+ stepHandlers.push([element, evt, advanceFn]);
28522
+ detachEvent(element, evt, advanceFn, true);
28523
+ attachEvent(element, evt, advanceFn, true);
28524
+ };
28525
+
28164
28526
  var registeredPlugins = [];
28165
28527
  var initialized$1 = false;
28166
28528
  const PluginAPI = {
@@ -28211,7 +28573,8 @@ const PluginAPI = {
28211
28573
  registerDisplayableGuides,
28212
28574
  removeDisplayableGuides,
28213
28575
  GuideFactory,
28214
- GuideStepFactory
28576
+ GuideStepFactory,
28577
+ AdvanceTrigger
28215
28578
  },
28216
28579
  hosts: {
28217
28580
  SERVER
@@ -28960,7 +29323,7 @@ function autoInitialize() {
28960
29323
  }
28961
29324
  flushCallQueue();
28962
29325
  }
28963
- function startup(callQueue, autoInitialize, whenLoadedCall) {
29326
+ function startup(callQueue, autoInitialize) {
28964
29327
  const disableAutoInitialize = ConfigReader.get('disableAutoInitialize');
28965
29328
  if (disableAutoInitialize)
28966
29329
  return;
@@ -28970,7 +29333,9 @@ function startup(callQueue, autoInitialize, whenLoadedCall) {
28970
29333
  autoInitialize();
28971
29334
  }
28972
29335
  else {
28973
- teardownFns.push(whenLoadedCall(autoInitialize));
29336
+ teardownFns.push(whenLoadedCall(() => {
29337
+ teardownFns.push(whenVisibleCall(autoInitialize));
29338
+ }));
28974
29339
  }
28975
29340
  }
28976
29341
  /**
@@ -34826,6 +35191,8 @@ const IFrameMonitor = (function () {
34826
35191
  return true;
34827
35192
  if (frame.pendo && (frame.pendo.initialize || frame.pendo.iframeWaiting))
34828
35193
  return true;
35194
+ if (frame.document && frame.document.body && !frame.document.body.hasChildNodes())
35195
+ return true;
34829
35196
  return scriptExists(frame);
34830
35197
  }
34831
35198
  function appendScriptTagToFrame(frame, agentUrl) {
@@ -34923,278 +35290,6 @@ const IFrameMonitor = (function () {
34923
35290
  }
34924
35291
  })();
34925
35292
 
34926
- function arrayEquals(array1, array2) {
34927
- if (array1.length != array2.length)
34928
- return false;
34929
- return _.all(array1, function (item, i) {
34930
- return item === array2[i];
34931
- });
34932
- }
34933
- class DOMActivationPhase {
34934
- constructor(DOMActivation) {
34935
- this.maxTargets = 50;
34936
- this.domActivation = DOMActivation;
34937
- this.name = 'dom';
34938
- this.queue = [];
34939
- }
34940
- markDirty() {
34941
- this.queue.push.apply(this.queue, this.domActivation.guides);
34942
- }
34943
- process(monitor) {
34944
- var domActivationGuide = this.queue.shift();
34945
- if (!domActivationGuide)
34946
- return;
34947
- monitor.saveContext(domActivationGuide);
34948
- var targets;
34949
- try {
34950
- targets = SizzleProxy(domActivationGuide.selector);
34951
- }
34952
- catch (e) {
34953
- targets = [];
34954
- }
34955
- if (targets.length > this.maxTargets) {
34956
- targets.length = this.maxTargets;
34957
- }
34958
- if (!arrayEquals(targets, domActivationGuide.targets)) {
34959
- domActivationGuide.targets = targets;
34960
- this.domActivation.detach(domActivationGuide, this.domActivation.targets);
34961
- _.each(targets, function (target) {
34962
- this.domActivation.attach(target, domActivationGuide, this.domActivation.targets);
34963
- }, this);
34964
- }
34965
- }
34966
- handleProcessTimeExceeded(monitor) {
34967
- const ctx = monitor.getContext();
34968
- if (ctx) {
34969
- log.warn('Element activated guide (' + ctx.id + ') timeout exceeded');
34970
- }
34971
- }
34972
- cancel() {
34973
- this.queue.length = 0;
34974
- }
34975
- isComplete() {
34976
- return !this.queue.length;
34977
- }
34978
- }
34979
- var DOMActivation = (function () {
34980
- var keyAttr = 'pendoTargetId';
34981
- var pluginApi;
34982
- /*
34983
- domActivatedGuides = [
34984
- {
34985
- id: 'aGuideId',
34986
- events: ['click', 'mouseover'],
34987
- selector: '.selector .for .target',
34988
- targets: [array, of, dom, references]
34989
- }
34990
- ]
34991
- */
34992
- var domActivatedGuides = [];
34993
- /*
34994
- activationTargets = {
34995
- aGuideId: 'aTargetId',
34996
- aTargetId: {
34997
- target: {{referenceToDomElement}},
34998
- events: {
34999
- click: {
35000
- guideIds: {
35001
- aGuideId: 1,
35002
- anotherGuideId: 1
35003
- },
35004
- fn: {{partial(eventHandler, guideIds)}}
35005
- },
35006
- mouseover: {{same format as click}}
35007
- }
35008
- }
35009
- {{more guide and target ids...}}
35010
- }
35011
- */
35012
- var activationTargets = {};
35013
- var domPhase;
35014
- return {
35015
- name: 'DOMActivation',
35016
- key: keyAttr,
35017
- guides: domActivatedGuides,
35018
- targets: activationTargets,
35019
- reset,
35020
- init,
35021
- attach: attachGuideToTarget,
35022
- detach: detachGuideFromTarget,
35023
- handler: eventHandler,
35024
- activates,
35025
- prefetch,
35026
- initialize,
35027
- teardown
35028
- };
35029
- function initialize(pendo, PluginAPI) {
35030
- pluginApi = PluginAPI;
35031
- PluginAPI.Events.on('deliverablesLoaded', reset);
35032
- PluginAPI.Events.on('guideListChanged', handleGuideListChanged);
35033
- PluginAPI.Events.on('guidesLoaded', handleGuidesLoaded);
35034
- domPhase = new DOMActivationPhase(DOMActivation);
35035
- addUpdatePhase(domPhase);
35036
- }
35037
- function teardown() {
35038
- removeUpdatePhase(domPhase);
35039
- pluginApi.Events.off('deliverablesLoaded', reset);
35040
- pluginApi.Events.off('guideListChanged', handleGuideListChanged);
35041
- pluginApi.Events.off('guidesLoaded', handleGuidesLoaded);
35042
- }
35043
- function handleGuideListChanged() {
35044
- reset();
35045
- init(getLocalActiveGuides());
35046
- }
35047
- function handleGuidesLoaded() {
35048
- prefetch(getLocalActiveGuides());
35049
- }
35050
- function attachGuideToTarget(target, domActivationGuide, activationTargets) {
35051
- var targetKey = target[keyAttr];
35052
- var handler = targetKey ? activationTargets[targetKey] : null;
35053
- if (!handler) {
35054
- targetKey = targetKey || 'target' + _.uniqueId();
35055
- handler = {
35056
- target,
35057
- events: {}
35058
- };
35059
- activationTargets[targetKey] = handler;
35060
- target[keyAttr] = targetKey;
35061
- }
35062
- var targetList = activationTargets[domActivationGuide.id] || [];
35063
- targetList.push(targetKey);
35064
- activationTargets[domActivationGuide.id] = targetList;
35065
- _.each(domActivationGuide.events, function (eventType) {
35066
- var eventTypeHandler = handler.events[eventType];
35067
- if (!eventTypeHandler) {
35068
- eventTypeHandler = {
35069
- guideIds: {}
35070
- };
35071
- eventTypeHandler.fn = _.partial(eventHandler, _, eventTypeHandler.guideIds);
35072
- if (eventType === 'mouseover') {
35073
- eventType = 'mouseenter';
35074
- }
35075
- attachEvent(target, eventType, eventTypeHandler.fn);
35076
- handler.events[eventType] = eventTypeHandler;
35077
- }
35078
- eventTypeHandler.guideIds[domActivationGuide.id] = 1;
35079
- });
35080
- }
35081
- function detachGuideFromTarget(domActivationGuide, activationTargets) {
35082
- _.each(activationTargets[domActivationGuide.id], function (targetKey) {
35083
- var handler = targetKey ? activationTargets[targetKey] : null;
35084
- if (handler) {
35085
- _.each(handler.events, function (eventTypeHandler, eventType) {
35086
- if (eventTypeHandler && eventTypeHandler.guideIds) {
35087
- delete eventTypeHandler.guideIds[domActivationGuide.id];
35088
- if (_.size(eventTypeHandler.guideIds) <= 0) {
35089
- if (eventType === 'mouseover') {
35090
- eventType = 'mouseenter';
35091
- }
35092
- detachEvent(handler.target, eventType, eventTypeHandler.fn);
35093
- delete handler.events[eventType];
35094
- }
35095
- }
35096
- });
35097
- if (_.size(handler.events) <= 0) {
35098
- delete handler.target[keyAttr];
35099
- handler.target = null;
35100
- delete activationTargets[targetKey];
35101
- }
35102
- }
35103
- });
35104
- delete activationTargets[domActivationGuide.id];
35105
- }
35106
- function eventHandler(e, guideIds) {
35107
- if (e.pendoActivatedGuide || dom.data.get(e, 'advanced')) {
35108
- return;
35109
- }
35110
- var prioritizeAdoptGuides = ConfigReader.get('adoptPrioritizeAdoptGuides');
35111
- var guides = _.compact(_.map(_.keys(guideIds), function (id) {
35112
- return findGuideById(id);
35113
- }));
35114
- guides = _.filter(guides, function (guide) {
35115
- if (!guide.steps || !guide.steps.length) {
35116
- return false;
35117
- }
35118
- if (_.get(guide, 'attributes.dom.isOnlyShowOnce')) {
35119
- return !guide.steps[0].hasBeenSeen();
35120
- }
35121
- return true;
35122
- });
35123
- guides = _(guides).chain()
35124
- .sortBy(function (guide) {
35125
- return guide.state === 'staged' ? 0 : 1;
35126
- })
35127
- .sortBy(function (guide) {
35128
- var isAdoptGuide = guide.isTraining;
35129
- if (prioritizeAdoptGuides) {
35130
- return isAdoptGuide ? 0 : 1;
35131
- }
35132
- return isAdoptGuide ? 1 : 0;
35133
- })
35134
- .value();
35135
- var activatedGuide = _.find(guides, function (guide) {
35136
- var firstStep = _.first(guide.steps);
35137
- var isResourceCenter = _.get(guide, 'attributes.resourceCenter', false);
35138
- if (isResourceCenter && guide.isShown()) {
35139
- return BuildingBlockResourceCenter.dismissResourceCenter();
35140
- }
35141
- if (!firstStep.canShow())
35142
- return false;
35143
- if (guide.isShown())
35144
- return true;
35145
- return showGuide(firstStep, 'dom');
35146
- });
35147
- if (activatedGuide) {
35148
- e.pendoActivatedGuide = activatedGuide.id;
35149
- }
35150
- }
35151
- function reset() {
35152
- _.each(domActivatedGuides, function (domActivationGuide) {
35153
- detachGuideFromTarget(domActivationGuide, activationTargets);
35154
- domActivationGuide.targets = [];
35155
- });
35156
- domActivatedGuides.length = 0;
35157
- }
35158
- function activates(guide) {
35159
- if (!guide.id || !guide.steps || !guide.steps.length || !guide.hasLaunchMethod('dom'))
35160
- return;
35161
- if (!guide.steps[0].canShowOnPage(getNormalizedUrl()))
35162
- return;
35163
- var events = _.get(guide, 'attributes.activation.event', []);
35164
- if (!events || !events.length)
35165
- return;
35166
- var selector = getActivationSelector(guide);
35167
- if (!selector)
35168
- return;
35169
- return {
35170
- id: guide.id,
35171
- events,
35172
- selector,
35173
- targets: []
35174
- };
35175
- }
35176
- function init(guideList) {
35177
- _.each(guideList, function (guide) {
35178
- var domActivatedGuide = activates(guide);
35179
- if (domActivatedGuide) {
35180
- domActivatedGuides.push(domActivatedGuide);
35181
- }
35182
- });
35183
- }
35184
- function prefetch(guides) {
35185
- if (ConfigReader.get('disablePrefetch')) {
35186
- return;
35187
- }
35188
- _.each(guides, function (guide) {
35189
- if (!_.isFunction(guide.hasLaunchMethod) || !guide.hasLaunchMethod('dom'))
35190
- return;
35191
- if (!guide.steps || !guide.steps.length || !_.isFunction(guide.steps[0].fetchContent))
35192
- return;
35193
- guide.steps[0].fetchContent(true);
35194
- });
35195
- }
35196
- })();
35197
-
35198
35293
  var designer;
35199
35294
  function designerExports() {
35200
35295
  return {
@@ -35564,72 +35659,6 @@ var PromoteMetadata = (function () {
35564
35659
  }
35565
35660
  })();
35566
35661
 
35567
- function AdvanceTrigger(element, method, step) {
35568
- this.element = element;
35569
- if (method == 'element') {
35570
- this.method = 'click';
35571
- }
35572
- else if (method == 'hover') {
35573
- this.method = 'mouseover';
35574
- }
35575
- else {
35576
- this.method = method;
35577
- }
35578
- this.step = step;
35579
- this.guide = step.getGuide();
35580
- }
35581
- AdvanceTrigger.prototype.add = function () {
35582
- if (_.indexOf(this.guide.steps, this.step) === 0 && !AdvanceTrigger.shouldAttachHandler(this.guide, this.method))
35583
- return;
35584
- if (!isBadge(this.guide) || isWalkthrough(this.guide)) {
35585
- this.setupElementEvent(this.element, this.method);
35586
- }
35587
- };
35588
- AdvanceTrigger.prototype.remove = function () {
35589
- this.teardownElementEvent(this.element, this.method);
35590
- };
35591
- // HTBD: (aka Here There Be Dragons)
35592
- // Instead of detaching on hide, we're going to leave the
35593
- // attach live until it's either advanced, dismissed or
35594
- // re-rendered. The reason for this is it's too easy for
35595
- // a race case to happen where the hide for this guide can
35596
- // happen before the element click event happens and thus we
35597
- // never get the onguideadvanced action being called.
35598
- AdvanceTrigger.prototype.setupElementEvent = function (element, evt) {
35599
- if (!this.advanceFn) {
35600
- this.advanceFn = _.compose(_.bind(this.teardownElementEvent, this, element, evt), _.bind(this.step.advance, this.step));
35601
- }
35602
- AdvanceTrigger.attach(this.step, element, evt, this.advanceFn);
35603
- };
35604
- AdvanceTrigger.prototype.teardownElementEvent = function (element, evt) {
35605
- log.info('detach onGuideAdvanced', { contexts: ['guide'] });
35606
- detachEvent(element, evt, this.advanceFn, true);
35607
- this.step.removeTrigger(this);
35608
- };
35609
- AdvanceTrigger.shouldAttachHandler = function shouldAttachHandler(guide, method) {
35610
- return !guide.isActivatedByEvent(method) ||
35611
- DOMActivation.activates(guide) ||
35612
- (guide.attributes.activation.selector !== guide.steps[0].elementPathRule &&
35613
- !!guide.attributes.activation.selector);
35614
- };
35615
- AdvanceTrigger.attach = function (step, element, evt, advanceFn) {
35616
- if (!step)
35617
- return;
35618
- var handlers = AdvanceTrigger.handlers = AdvanceTrigger.handlers || {};
35619
- var stepHandlers = handlers[step.id] = handlers[step.id] || [];
35620
- for (var i = 0; i < stepHandlers.length; ++i) {
35621
- var handler = stepHandlers[i];
35622
- if (element === handler[0] && evt === handler[1]) {
35623
- detachEvent(element, evt, handler[2], true);
35624
- stepHandlers.splice(_.indexOf(stepHandlers, handler), 1);
35625
- i--;
35626
- }
35627
- }
35628
- stepHandlers.push([element, evt, advanceFn]);
35629
- detachEvent(element, evt, advanceFn, true);
35630
- attachEvent(element, evt, advanceFn, true);
35631
- };
35632
-
35633
35662
  var TOOLTIP_DEFAULT_WIDTH = 430;
35634
35663
  var TOOLTIP_DEFAULT_HEIGHT = 200;
35635
35664
  var TOOLTIP_ARROW_SIZE = 15;
@@ -40641,7 +40670,7 @@ function initAgent(pendo, PendoConfig) {
40641
40670
  populatePendoObject(pendo);
40642
40671
  log.addEventListener('log', _.partial(store.dispatch, 'errorLog/write'));
40643
40672
  registerBuiltInPlugins();
40644
- startup(pendo._q, autoInitialize, whenLoadedCall);
40673
+ startup(pendo._q, autoInitialize);
40645
40674
  return true;
40646
40675
  }
40647
40676
 
@@ -54396,7 +54425,15 @@ class SessionRecorder {
54396
54425
  this._startRecordingForVisitor(visitorConfig);
54397
54426
  }).catch((e) => {
54398
54427
  this.restartPtm();
54399
- this.api.log.critical('Failed to fetch recording config', { error: e });
54428
+ if (e && /Failed to fetch/.test(e.toString())) {
54429
+ return;
54430
+ }
54431
+ this.api.log.critical('Failed to fetch recording config', {
54432
+ error: e,
54433
+ visitorId: this.visitorId,
54434
+ accountId: this.accountId,
54435
+ url: this.pendo.url.get()
54436
+ });
54400
54437
  this.logStopReason('VISITOR_CONFIG_ERROR');
54401
54438
  });
54402
54439
  }
@@ -55453,8 +55490,10 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
55453
55490
 
55454
55491
  const ONE_HUNDRED_MB_IN_BYTES = 100 * 1024 * 1024;
55455
55492
  function matchHostedResources(recordingEvent, stringifiedRecordingPayload) {
55456
- const fontURLRegex = /https:\/\/[^\s]+?\.(woff2?|ttf|otf|eot)(\?[^\s]*)?\b/g;
55457
- const hostedResources = stringifiedRecordingPayload.match(fontURLRegex);
55493
+ const fontURLRegex = /https:\/\/[^"\\\s]+?\.(woff2?|ttf|otf|eot)(\?[^"\\\s]*)?\b/g;
55494
+ const matches = stringifiedRecordingPayload.match(fontURLRegex);
55495
+ // de-duplicate matches
55496
+ const hostedResources = matches ? Array.from(new Set(matches)) : [];
55458
55497
  return {
55459
55498
  type: 'recording',
55460
55499
  visitorId: recordingEvent.visitorId,
@@ -55469,7 +55508,7 @@ var WorkerFactory = /*#__PURE__*/createInlineWorkerFactory(/* rollup-plugin-web-
55469
55508
  recordingPayloadMetadata: [],
55470
55509
  sequence: 0,
55471
55510
  recordingPayloadCount: 0,
55472
- hostedResources: hostedResources || []
55511
+ hostedResources
55473
55512
  };
55474
55513
  }
55475
55514
  // keep in mind changes here may need addressing in the extension worker proxy as well
@@ -56734,6 +56773,17 @@ var ConfigReader = (function () {
56734
56773
  */
56735
56774
  addOption('dataHost', [SNIPPET_SRC, PENDO_CONFIG_SRC]);
56736
56775
  addOption('disableAutoInitialize');
56776
+ /**
56777
+ * If set to `true` the web SDK will wait for the host application to be both loaded and visible before
56778
+ * starting the initialization process.
56779
+ *
56780
+ * @access public
56781
+ * @category Config/Core
56782
+ * @name initializeWhenVisible
56783
+ * @default false
56784
+ * @type {boolean}
56785
+ */
56786
+ addOption('initializeWhenVisible', [SNIPPET_SRC, PENDO_CONFIG_SRC], false);
56737
56787
  /**
56738
56788
  * Although the name refers to cookies, if set to `true` the web SDK will not persist any data in local
56739
56789
  * storage or cookies and will rely only on memory.
@@ -58926,7 +58976,7 @@ const PREDICT_STEP_REGEX = /\$\$predict\$\$/;
58926
58976
  const DRAG_THRESHOLD = 5;
58927
58977
  const STYLE_ID = 'pendo-predict-plugin-styles';
58928
58978
  const PREDICT_BASE_URL = 'https://predict.pendo.io';
58929
- const BUTTON_CLASS_IDENTIFIER = '._pendo-button-primaryButton:contains("token")';
58979
+ const GUIDE_BUTTON_IDENTIFIER = 'button:contains("token")';
58930
58980
  const pluginVersion = '1.0.0';
58931
58981
  const $ = (id) => document.getElementById(id);
58932
58982
  const createElement = (tag, attrs = {}, parent = null) => {
@@ -58945,10 +58995,13 @@ const createElement = (tag, attrs = {}, parent = null) => {
58945
58995
  parent.appendChild(el);
58946
58996
  return el;
58947
58997
  };
58948
- const injectStyles = (pendoContainerId) => {
58998
+ const injectStyles = (pendoContainerId, log = () => { }) => {
58949
58999
  const styleId = `${STYLE_ID}-${pendoContainerId}`;
58950
- if ($(styleId))
59000
+ if ($(styleId)) {
59001
+ log(`[predict] style already exists, skipping: ${styleId}`);
58951
59002
  return;
59003
+ }
59004
+ log(`[predict] injecting styles: ${styleId}`);
58952
59005
  createElement('style', {
58953
59006
  id: styleId,
58954
59007
  textContent: `
@@ -58997,10 +59050,12 @@ const injectStyles = (pendoContainerId) => {
58997
59050
  `
58998
59051
  }, document.head);
58999
59052
  };
59000
- const getRecordIdFromUrl = (recordRegex) => {
59053
+ const getRecordIdFromUrl = (recordRegex, log = () => { }) => {
59001
59054
  var _a;
59002
59055
  const match = window.location.href.match(recordRegex);
59003
- return (_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : null;
59056
+ const recordId = (_a = match === null || match === void 0 ? void 0 : match[1]) !== null && _a !== void 0 ? _a : null;
59057
+ log(`[predict] recordId found: ${recordId}`);
59058
+ return recordId;
59004
59059
  };
59005
59060
  const safeStringify = (value, fallback) => {
59006
59061
  try {
@@ -59010,11 +59065,12 @@ const safeStringify = (value, fallback) => {
59010
59065
  return fallback !== null && fallback !== void 0 ? fallback : '';
59011
59066
  }
59012
59067
  };
59013
- const safeParse = (value, fallback) => {
59068
+ const safeParse = (value, fallback, log = () => { }) => {
59014
59069
  try {
59015
59070
  return JSON.parse(value);
59016
59071
  }
59017
59072
  catch (error) {
59073
+ log(`[predict] JSON parse error: ${error}`);
59018
59074
  return fallback;
59019
59075
  }
59020
59076
  };
@@ -59158,10 +59214,9 @@ const createFloatingModal = ({ recordId, configuration }) => {
59158
59214
  }, container);
59159
59215
  container.dragHandle = setupDragAndDrop(dragHandle, container);
59160
59216
  return () => {
59161
- var _a, _b, _c;
59217
+ var _a, _b;
59162
59218
  (_b = (_a = container.dragHandle) === null || _a === void 0 ? void 0 : _a.cleanup) === null || _b === void 0 ? void 0 : _b.call(_a);
59163
59219
  container.remove();
59164
- const flatIds = (_c = configuration.analysisIds) === null || _c === void 0 ? void 0 : _c.flat(Infinity);
59165
59220
  for (let i = 0; i < flatIds.length; i++) {
59166
59221
  const frame = $(`frameExplanation-${flatIds[i]}`);
59167
59222
  if (frame)
@@ -59253,23 +59308,33 @@ const setupMessageListener = ({ token, cleanup, pendo }) => {
59253
59308
  window.addEventListener('message', messageHandler);
59254
59309
  return () => window.removeEventListener('message', messageHandler);
59255
59310
  };
59256
- const predictGuidesScript = ({ step, pendo, cleanupArray, cleanup }) => {
59311
+ const predictGuidesScript = ({ step, pendo, cleanupArray, cleanup, log }) => {
59257
59312
  var _a;
59258
- if (cleanupArray.length > 0)
59313
+ log('[predict] initializing');
59314
+ // Before anything else, inject styles so that the guide will be hidden
59315
+ const pendoContainerId = step === null || step === void 0 ? void 0 : step.containerId;
59316
+ injectStyles(pendoContainerId, log);
59317
+ if (cleanupArray.length > 0) {
59318
+ log('[predict] cleanupArray is not empty');
59259
59319
  return;
59320
+ }
59260
59321
  // ----- Extract Configuration -----
59261
- const pendoButtonPrimaryButton = (_a = step.guideElement.find(BUTTON_CLASS_IDENTIFIER)) === null || _a === void 0 ? void 0 : _a[0];
59262
- if (!pendoButtonPrimaryButton)
59322
+ const guideButton = (_a = step.guideElement.find(GUIDE_BUTTON_IDENTIFIER)) === null || _a === void 0 ? void 0 : _a[0];
59323
+ if (!guideButton) {
59324
+ log('[predict] no guide button found, aborting');
59263
59325
  return;
59264
- const _b = safeParse(pendoButtonPrimaryButton.textContent, null), { token } = _b, configuration = __rest(_b, ["token"]);
59265
- if (!configuration)
59326
+ }
59327
+ const _b = safeParse(guideButton.textContent, {}, log), { token } = _b, configuration = __rest(_b, ["token"]);
59328
+ if (!configuration || !token) {
59329
+ log('[predict] no configuration found, aborting');
59266
59330
  return;
59267
- const pendoContainerId = step === null || step === void 0 ? void 0 : step.containerId;
59268
- injectStyles(pendoContainerId);
59269
- const recordRegex = new RegExp(`/${configuration.recordRegexName}/([a-zA-Z0-9]{15,18})(?:/|$)`);
59270
- const recordId = getRecordIdFromUrl(recordRegex);
59271
- if (!recordId)
59331
+ }
59332
+ const recordRegex = new RegExp(`/${configuration.recordRegexName}/([a-zA-Z0-9]+)(?:/|$)`);
59333
+ const recordId = getRecordIdFromUrl(recordRegex, log);
59334
+ if (!recordId) {
59335
+ log('[predict] no recordId found in URL, aborting');
59272
59336
  return;
59337
+ }
59273
59338
  cleanupArray.push(setupMessageListener({ token, cleanup, pendo }));
59274
59339
  cleanupArray.push(createFloatingModal({ recordId, configuration }));
59275
59340
  };
@@ -59278,11 +59343,13 @@ const PredictGuides = () => {
59278
59343
  let pluginApiRef = null;
59279
59344
  let cleanupArray = [];
59280
59345
  const cleanup = () => {
59346
+ var _a;
59347
+ (_a = pluginApiRef === null || pluginApiRef === void 0 ? void 0 : pluginApiRef.log) === null || _a === void 0 ? void 0 : _a.debug('[predict] cleaning up');
59281
59348
  for (let i = 0; i < cleanupArray.length; i++) {
59282
59349
  try {
59283
59350
  cleanupArray[i]();
59284
59351
  }
59285
- catch (_a) { }
59352
+ catch (_b) { }
59286
59353
  }
59287
59354
  cleanupArray = [];
59288
59355
  };
@@ -59297,11 +59364,12 @@ const PredictGuides = () => {
59297
59364
  const predictGuidesEnabled = configReader.get(PREDICT_GUIDES_CONFIG);
59298
59365
  if (!predictGuidesEnabled)
59299
59366
  return;
59367
+ const log = PluginAPI.log.debug.bind(PluginAPI.log);
59300
59368
  pluginApiRef.Events.urlChanged.on(cleanup);
59301
59369
  const script = {
59302
59370
  name: 'PredictFrameScript',
59303
59371
  script(step, _guide, pendo) {
59304
- predictGuidesScript({ step, pendo, cleanupArray, cleanup });
59372
+ predictGuidesScript({ step, pendo, cleanupArray, cleanup, log });
59305
59373
  this.on('unmounted', (evt) => {
59306
59374
  if (evt.reason !== 'hidden')
59307
59375
  cleanup();