@pendo/agent 2.287.0 → 2.288.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 CHANGED
@@ -7287,7 +7287,7 @@ function getScreenPosition(element) {
7287
7287
  };
7288
7288
  }
7289
7289
 
7290
- var VERSION = '2.287.0_';
7290
+ var VERSION = '2.288.0_';
7291
7291
 
7292
7292
  var decodeURIComponent = _.isFunction(window.decodeURIComponent) ? window.decodeURIComponent : _.identity;
7293
7293
 
@@ -3903,8 +3903,8 @@ var SERVER = '';
3903
3903
  var ASSET_HOST = '';
3904
3904
  var ASSET_PATH = '';
3905
3905
  var DESIGNER_SERVER = '';
3906
- var VERSION = '2.287.0_';
3907
- var PACKAGE_VERSION = '2.287.0';
3906
+ var VERSION = '2.288.0_';
3907
+ var PACKAGE_VERSION = '2.288.0';
3908
3908
  var LOADER = 'xhr';
3909
3909
  /* eslint-enable agent-eslint-rules/no-gulp-env-references */
3910
3910
  /**
@@ -12149,8 +12149,13 @@ class LocalStorageEventBuffer {
12149
12149
  * @label UNSENT_EVENTS_KEY
12150
12150
  */
12151
12151
  storage.registry.addLocal(UNSENT_EVENTS_KEY);
12152
- this.events = JSON.parse(storage.read(UNSENT_EVENTS_KEY) || '{}');
12153
- storage.clear(UNSENT_EVENTS_KEY);
12152
+ try {
12153
+ this.events = JSON.parse(storage.read(UNSENT_EVENTS_KEY) || '{}');
12154
+ storage.clear(UNSENT_EVENTS_KEY);
12155
+ }
12156
+ catch (e) {
12157
+ this.events = {};
12158
+ }
12154
12159
  }
12155
12160
  write(storage) {
12156
12161
  if (_.size(this.events) > 0) {
@@ -38060,7 +38065,7 @@ const FormValidation = (function () {
38060
38065
  })();
38061
38066
 
38062
38067
  class DOMPrompt {
38063
- constructor(pendo, PluginAPI, id, privacyFitlers, inputCssSelector, submitCssSelector) {
38068
+ constructor(pendo, PluginAPI, id, privacyFilters, inputCssSelectors, submitCssSelectors) {
38064
38069
  this.listeners = [];
38065
38070
  this.latestPromptValue = '';
38066
38071
  this.dom = pendo.dom;
@@ -38068,27 +38073,69 @@ class DOMPrompt {
38068
38073
  this.api = PluginAPI;
38069
38074
  this.q = PluginAPI.q;
38070
38075
  this.id = id;
38071
- this.setFilters(privacyFitlers);
38072
- this.inputEl = new this.dom.Element(inputCssSelector);
38073
- this.submitEl = new this.dom.Element(submitCssSelector);
38074
- this.inputEl.addEventListener('change', (evt) => {
38075
- // capture value from copy / paste
38076
- this.capturePromptValue();
38077
- }, true);
38078
- this.inputEl.addEventListener('keydown', (evt) => {
38079
- const wasEnterKey = evt.code === 'Enter' || evt.key === 'Enter' || evt.keyCode === 13;
38080
- if (wasEnterKey) {
38081
- this.submit(this.latestPromptValue);
38076
+ this.setFilters(privacyFilters);
38077
+ if (!this._.isArray(inputCssSelectors)) {
38078
+ this.api.log.error('inputCssSelectors must be an array, received:', typeof inputCssSelectors);
38079
+ inputCssSelectors = [];
38080
+ }
38081
+ if (!this._.isArray(submitCssSelectors)) {
38082
+ this.api.log.error('submitCssSelectors must be an array, received:', typeof submitCssSelectors);
38083
+ submitCssSelectors = [];
38084
+ }
38085
+ this.inputEls = this._.map(inputCssSelectors, cssSelector => new this.dom.Element(cssSelector));
38086
+ this.submitEls = this._.map(submitCssSelectors, cssSelector => new this.dom.Element(cssSelector));
38087
+ this.setupInputListeners();
38088
+ this.setupSubmitListeners();
38089
+ this.setupObserver();
38090
+ }
38091
+ setupInputListeners() {
38092
+ this._.each(this.inputEls, (inputEl) => {
38093
+ if (!inputEl) {
38094
+ return;
38082
38095
  }
38083
- }, true);
38084
- this.inputEl.addEventListener('keyup', (evt) => {
38085
- this.capturePromptValue();
38086
- }, true);
38087
- this.submitEl.addEventListener('click', () => {
38088
- this.submit(this.latestPromptValue);
38089
- }, true);
38096
+ inputEl.addEventListener('change', (evt) => {
38097
+ // capture value from copy / paste
38098
+ this.capturePromptValue();
38099
+ }, true);
38100
+ inputEl.addEventListener('keydown', (evt) => {
38101
+ const wasEnterKey = evt.code === 'Enter' || evt.key === 'Enter' || evt.keyCode === 13;
38102
+ if (wasEnterKey) {
38103
+ this.submit(this.latestPromptValue);
38104
+ }
38105
+ }, true);
38106
+ inputEl.addEventListener('keyup', (evt) => {
38107
+ this.capturePromptValue();
38108
+ }, true);
38109
+ });
38110
+ }
38111
+ setupSubmitListeners() {
38112
+ this._.each(this.submitEls, (submitEl) => {
38113
+ if (!submitEl) {
38114
+ return;
38115
+ }
38116
+ const clickHandler = (evt) => {
38117
+ // Capture current value at mousedown time, before app's click handlers run
38118
+ const currentValue = this.getPromptValue();
38119
+ const valueToSubmit = currentValue || this.latestPromptValue;
38120
+ this.submit(valueToSubmit);
38121
+ };
38122
+ submitEl.addEventListener('mousedown', clickHandler, true);
38123
+ const keydownHandler = (evt) => {
38124
+ const wasEnterKey = evt.code === 'Enter' || evt.key === 'Enter' || evt.keyCode === 13;
38125
+ if (wasEnterKey) {
38126
+ const currentValue = this.getPromptValue();
38127
+ const valueToSubmit = currentValue || this.latestPromptValue;
38128
+ this.submit(valueToSubmit);
38129
+ }
38130
+ };
38131
+ submitEl.addEventListener('keydown', keydownHandler, true);
38132
+ });
38133
+ }
38134
+ setupObserver() {
38090
38135
  this.promptContainer = new this.dom.Observer();
38091
- this.promptContainer.addObservers(this.inputEl, this.submitEl);
38136
+ const validInputEls = this._.filter(this.inputEls, el => el);
38137
+ const validSubmitEls = this._.filter(this.submitEls, el => el);
38138
+ this.promptContainer.addObservers(...validInputEls, ...validSubmitEls);
38092
38139
  }
38093
38140
  setFilters(candidateFilter) {
38094
38141
  if (!candidateFilter) {
@@ -38111,11 +38158,10 @@ class DOMPrompt {
38111
38158
  return candidateValue.replace(filtersToUse, 'redacted');
38112
38159
  }
38113
38160
  submit(origVal) {
38114
- // Don't submit an empty prompt
38115
- if (!origVal)
38161
+ if (!origVal) {
38116
38162
  return;
38163
+ }
38117
38164
  const val = this.applyPrivacyFilter(origVal);
38118
- // build the payload: id, value, was filter used
38119
38165
  const payload = {
38120
38166
  agentId: this.id,
38121
38167
  prompt: val,
@@ -38124,7 +38170,7 @@ class DOMPrompt {
38124
38170
  this._.each(this.listeners, (cb) => cb(payload));
38125
38171
  }
38126
38172
  /*
38127
- * Genernally we want to capture the value from "input" but there can be implementation
38173
+ * Generally we want to capture the value from "input" but there can be implementation
38128
38174
  * dependent scenarios where the input's value has already been cleared by the time
38129
38175
  * the event handler is called. So, in that case, we don't want to throw our saved value out.
38130
38176
  */
@@ -38136,15 +38182,44 @@ class DOMPrompt {
38136
38182
  return tmp;
38137
38183
  }
38138
38184
  getPromptValue() {
38139
- return this.inputEl.getText();
38185
+ const elementWithValue = this._.find(this.inputEls, (el) => {
38186
+ if (el) {
38187
+ try {
38188
+ const value = el.getText();
38189
+ return value && value.trim();
38190
+ }
38191
+ catch (err) {
38192
+ return false;
38193
+ }
38194
+ }
38195
+ return false;
38196
+ });
38197
+ if (elementWithValue) {
38198
+ try {
38199
+ const value = elementWithValue.getText();
38200
+ return value.trim();
38201
+ }
38202
+ catch (err) { }
38203
+ }
38204
+ return '';
38140
38205
  }
38141
38206
  onSubmit(callback) {
38142
38207
  this.listeners.push(callback);
38143
38208
  }
38144
38209
  teardown() {
38145
- this.promptContainer.teardown();
38146
- this.inputEl.teardown();
38147
- this.submitEl.teardown();
38210
+ if (this.promptContainer) {
38211
+ this.promptContainer.teardown();
38212
+ }
38213
+ this._.each(this.inputEls, (inputEl) => {
38214
+ if (inputEl) {
38215
+ inputEl.teardown();
38216
+ }
38217
+ });
38218
+ this._.each(this.submitEls, (submitEl) => {
38219
+ if (submitEl) {
38220
+ submitEl.teardown();
38221
+ }
38222
+ });
38148
38223
  }
38149
38224
  }
38150
38225
 
@@ -38269,17 +38344,19 @@ class PromptPlugin {
38269
38344
  }
38270
38345
  observePrompt(config) {
38271
38346
  const { id, cssSelectors, privacyFilters } = config;
38272
- let inputCssSelector, submitCssSelector;
38273
- inputCssSelector = this.parseCssSelector('input', cssSelectors);
38274
- submitCssSelector = this.parseCssSelector('submit', cssSelectors);
38275
- const prompt = new DOMPrompt(this.pendo, this.api, id, privacyFilters, inputCssSelector, submitCssSelector);
38347
+ let inputCssSelectors, submitCssSelectors;
38348
+ inputCssSelectors = this.parseCssSelector('input', cssSelectors);
38349
+ submitCssSelectors = this.parseCssSelector('submit', cssSelectors);
38350
+ const prompt = new DOMPrompt(this.pendo, this.api, id, privacyFilters, inputCssSelectors, submitCssSelectors);
38276
38351
  prompt.onSubmit((promptPayload) => {
38277
38352
  this.sendEvent(promptPayload);
38278
38353
  });
38279
38354
  this.prompts.push(prompt);
38280
38355
  }
38281
38356
  parseCssSelector(type, configs) {
38282
- return this._.find(configs, (target) => target.type === type).cssSelector;
38357
+ const filtered = this._.filter(configs, cfg => cfg.type === type);
38358
+ const selectors = this._.map(filtered, cfg => cfg.cssSelector);
38359
+ return selectors;
38283
38360
  }
38284
38361
  sendEvent(promptEvent) {
38285
38362
  const event = this._.extend({
@@ -47234,6 +47311,12 @@ class SessionRecorder {
47234
47311
  * will ensure that it and the snapshot events are sent together and first for the next session of events.
47235
47312
  */
47236
47313
  if (isMeta) {
47314
+ // Replace the URL captured by rrweb for META events with the location API aware version of the URL. This
47315
+ // makes sure the URL captured in replay respects any URL modification/obfuscation set up by end users
47316
+ // using the location API.
47317
+ if (this.pendo._.has(event, 'data.href')) {
47318
+ event.data.href = this.pendo.location.getHref();
47319
+ }
47237
47320
  this.send();
47238
47321
  }
47239
47322
  this.buffer.push(event);