@4site/engrid-scripts 0.28.5 → 0.28.7

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/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { DonationAmount, DonationFrequency, EnForm, ProcessingFees, Country, } from "./events";
2
- import { AmountLabel, Loader, ProgressBar, UpsellLightbox, ENGrid, OptionsDefaults, setRecurrFreq, PageBackground, MediaAttribution, ApplePay, A11y, CapitalizeFields, Ecard, ClickToExpand, Advocacy, DataAttributes, LiveVariables, iFrame, InputPlaceholders, InputHasValueAndFocus, ShowHideRadioCheckboxes, AutoCountrySelect, SkipToMainContentLink, SrcDefer, NeverBounce, AutoYear, Autocomplete, RememberMe, TranslateFields, ShowIfAmount, EngridLogger, OtherAmount, MinMaxAmount, Ticker, DataReplace, DataHide, AddNameToMessage, ExpandRegionName, AppVersion, UrlToForm, RequiredIfVisible, TidyContact, DataLayer, LiveCurrency, Autosubmit, EventTickets, SwapAmounts, DebugPanel, DebugHiddenFields, FreshAddress, BrandingHtml, CountryDisable, PremiumGift, DigitalWallets, MobileCTA, LiveFrequency, UniversalOptIn, StripeFinancialConnections, GiveBySelect, UrlParamsToBodyAttrs, ExitIntentLightbox, SupporterHub, FastFormFill, SetAttr, ShowIfPresent, ENValidators, CustomCurrency, VGS, PostalCodeValidator, CountryRedirect, WelcomeBack, EcardToTarget, UsOnlyForm, ThankYouPageConditionalContent, EmbeddedEcard, CheckboxLabel, UpsellCheckbox, PostDonationEmbed, FrequencyUpsell, CustomPremium, StickyNSG, StickyPrepopulation, PreferredPaymentMethod, } from ".";
2
+ import { AmountLabel, Loader, ProgressBar, UpsellLightbox, ENGrid, OptionsDefaults, setRecurrFreq, PageBackground, MediaAttribution, ApplePay, A11y, CapitalizeFields, Ecard, ClickToExpand, Advocacy, DataAttributes, LiveVariables, iFrame, InputPlaceholders, InputHasValueAndFocus, ShowHideRadioCheckboxes, AutoCountrySelect, SkipToMainContentLink, SrcDefer, NeverBounce, AutoYear, Autocomplete, RememberMe, TranslateFields, ShowIfAmount, EngridLogger, OtherAmount, MinMaxAmount, Ticker, DataReplace, DataHide, AddNameToMessage, ExpandRegionName, AppVersion, UrlToForm, RequiredIfVisible, TidyContact, DataLayer, LiveCurrency, Autosubmit, EventTickets, SwapAmounts, DebugPanel, DebugHiddenFields, FreshAddress, BrandingHtml, CountryDisable, PremiumGift, DigitalWallets, MobileCTA, LiveFrequency, UniversalOptIn, StripeFinancialConnections, GiveBySelect, UrlParamsToBodyAttrs, ExitIntentLightbox, SupporterHub, FastFormFill, SetAttr, ShowIfPresent, ENValidators, CustomCurrency, VGS, PostalCodeValidator, CountryRedirect, WelcomeBack, EcardToTarget, UsOnlyForm, ThankYouPageConditionalContent, EmbeddedEcard, CheckboxLabel, UpsellCheckbox, PostDonationEmbed, FrequencyUpsell, CustomPremium, StickyNSG, StickyPrepopulation, PreferredPaymentMethod, TidyContactEmail, } from ".";
3
3
  export class App extends ENGrid {
4
4
  constructor(options) {
5
5
  super();
@@ -225,6 +225,10 @@ export class App extends ENGrid {
225
225
  // FreshAddress
226
226
  if (this.options.FreshAddress)
227
227
  new FreshAddress();
228
+ // TidyContact Email. Must stay below the window.enOnValidate assignment,
229
+ // so the TC Email bundle wraps ENgrid's hook instead of being overwritten by it.
230
+ if (this.options.TidyContactEmail)
231
+ new TidyContactEmail();
228
232
  new ShowIfAmount();
229
233
  new OtherAmount();
230
234
  new MinMaxAmount();
package/dist/iframe.d.ts CHANGED
@@ -1,9 +1,21 @@
1
1
  import { EnForm } from "./events";
2
2
  export declare class iFrame {
3
3
  _form: EnForm;
4
+ private resizeObserver;
4
5
  private logger;
5
6
  constructor();
6
7
  private onLoaded;
8
+ /**
9
+ * Observes document.body for size changes (DOM mutations, font/image
10
+ * loads, CSS transitions) and re-sends the iframe height to the parent.
11
+ *
12
+ * Uses a leading + trailing throttle via debounceWithImmediate: the
13
+ * first change is sent immediately, and the settled height is always
14
+ * re-sent once changes stop for 120ms. Animated transitions therefore
15
+ * don't flood the parent page with one message per frame, but the
16
+ * parent always ends up matching the final resolved height.
17
+ */
18
+ private observeHeightChanges;
7
19
  /**
8
20
  * Posts a `engrid-iframe-queue:thank-you` message to the parent window
9
21
  * when the embedded EN page reaches its Thank You page (the last page
package/dist/iframe.js CHANGED
@@ -3,6 +3,7 @@ import { EnForm } from "./events";
3
3
  export class iFrame {
4
4
  constructor() {
5
5
  this._form = EnForm.getInstance();
6
+ this.resizeObserver = null;
6
7
  this.logger = new EngridLogger("iFrame", "brown", "gray", "📡");
7
8
  if (this.inIframe()) {
8
9
  // Add the data-engrid-embedded attribute when inside an iFrame if it wasn't already added by a script in the Page Template
@@ -95,6 +96,7 @@ export class iFrame {
95
96
  if (iframe) {
96
97
  if (event.data.hasOwnProperty("frameHeight")) {
97
98
  iframe.style.height = event.data.frameHeight + "px";
99
+ this.logger.log(`iFrame Event - Resized iframe element to ${event.data.frameHeight}px`);
98
100
  if (event.data.frameHeight > 0) {
99
101
  iframe.classList.add("loaded");
100
102
  }
@@ -134,6 +136,8 @@ export class iFrame {
134
136
  // Scroll to top of iFrame
135
137
  this.logger.log("iFrame Event - window.onload");
136
138
  this.sendIframeHeight();
139
+ // Continuously re-send the height whenever the body size changes
140
+ this.observeHeightChanges();
137
141
  window.parent.postMessage({
138
142
  scroll: this.shouldScroll(),
139
143
  }, "*");
@@ -142,16 +146,40 @@ export class iFrame {
142
146
  // matches it by Page ID to advance to the next queued iframe. Fires
143
147
  // exactly once per Thank-You-page load. See iframe-queue.ts.
144
148
  this.sendIframeQueueThankYouPing();
145
- // On click fire the resize event
146
- document.addEventListener("click", (e) => {
147
- this.logger.log("iFrame Event - click");
148
- setTimeout(() => {
149
- this.sendIframeHeight();
150
- }, 100);
151
- });
152
149
  // Watch for errors and send the height
153
150
  ENGrid.watchForError(this.sendIframeHeight.bind(this));
154
151
  }
152
+ /**
153
+ * Observes document.body for size changes (DOM mutations, font/image
154
+ * loads, CSS transitions) and re-sends the iframe height to the parent.
155
+ *
156
+ * Uses a leading + trailing throttle via debounceWithImmediate: the
157
+ * first change is sent immediately, and the settled height is always
158
+ * re-sent once changes stop for 120ms. Animated transitions therefore
159
+ * don't flood the parent page with one message per frame, but the
160
+ * parent always ends up matching the final resolved height.
161
+ */
162
+ observeHeightChanges() {
163
+ if (typeof ResizeObserver === "undefined") {
164
+ this.logger.log("ResizeObserver not supported in this browser");
165
+ return;
166
+ }
167
+ let lastSent = -1;
168
+ const throttledSend = this.debounceWithImmediate((_entries, _observer, immediate) => {
169
+ const height = document.body.offsetHeight;
170
+ // Skip redundant sends when the settled height is unchanged
171
+ if (height === lastSent) {
172
+ this.logger.log(`iFrame Event - ResizeObserver settled at unchanged height ${height}px, skipping send`);
173
+ return;
174
+ }
175
+ lastSent = height;
176
+ this.logger.log(`iFrame Event - ResizeObserver ${immediate ? "leading" : "trailing"} resize: sending height ${height}px`);
177
+ this.sendIframeHeight();
178
+ }, 120);
179
+ this.resizeObserver = new ResizeObserver(throttledSend);
180
+ this.resizeObserver.observe(document.body);
181
+ this.logger.log("iFrame Event - Observing body resize");
182
+ }
155
183
  /**
156
184
  * Posts a `engrid-iframe-queue:thank-you` message to the parent window
157
185
  * when the embedded EN page reaches its Thank You page (the last page
@@ -299,11 +327,11 @@ export class iFrame {
299
327
  return (...args) => {
300
328
  clearTimeout(timer);
301
329
  if (firstEvent) {
302
- func.apply(this, args);
330
+ func.apply(this, [...args, true]);
303
331
  firstEvent = false;
304
332
  }
305
333
  timer = setTimeout(() => {
306
- func.apply(this, args);
334
+ func.apply(this, [...args, false]);
307
335
  firstEvent = true;
308
336
  }, timeout);
309
337
  };
package/dist/index.d.ts CHANGED
@@ -52,6 +52,7 @@ export * from "./expand-region-name";
52
52
  export * from "./url-to-form";
53
53
  export * from "./required-if-visible";
54
54
  export * from "./tidycontact";
55
+ export * from "./tidycontact-email";
55
56
  export * from "./live-currency";
56
57
  export * from "./custom-currency";
57
58
  export * from "./autosubmit";
package/dist/index.js CHANGED
@@ -52,6 +52,7 @@ export * from "./expand-region-name";
52
52
  export * from "./url-to-form";
53
53
  export * from "./required-if-visible";
54
54
  export * from "./tidycontact";
55
+ export * from "./tidycontact-email";
55
56
  export * from "./live-currency";
56
57
  export * from "./custom-currency";
57
58
  export * from "./autosubmit";
@@ -89,6 +89,17 @@ export interface Options {
89
89
  phone_date_field?: string;
90
90
  phone_status_field?: string;
91
91
  };
92
+ TidyContactEmail?: false | {
93
+ clientKey: string;
94
+ relayUrl?: string;
95
+ version?: string;
96
+ scriptUrl?: string;
97
+ timeoutMs?: number;
98
+ hardBlock?: boolean;
99
+ prefillSkip?: boolean;
100
+ enRecognition?: boolean;
101
+ pageTypes?: ("DONATION" | "ECARD" | "SURVEY" | "EMAILTOTARGET" | "ADVOCACY" | "SUBSCRIBEFORM" | "EVENT" | "SUPPORTERHUB" | "UNSUBSCRIBE" | "TWEETPAGE" | "UNKNOWN")[];
102
+ };
92
103
  MobileCTA?: false | {
93
104
  pageType: string;
94
105
  label: string;
@@ -30,6 +30,7 @@ export const OptionsDefaults = {
30
30
  Debug: false,
31
31
  RememberMe: false,
32
32
  TidyContact: false,
33
+ TidyContactEmail: false,
33
34
  RegionLongFormat: "",
34
35
  CountryDisable: [],
35
36
  Placeholders: false,
@@ -0,0 +1,7 @@
1
+ export declare class TidyContactEmail {
2
+ private logger;
3
+ private options;
4
+ constructor();
5
+ private shouldRun;
6
+ private loadScript;
7
+ }
@@ -0,0 +1,83 @@
1
+ import { ENGrid, EngridLogger } from ".";
2
+ // Same selector the TC Email bundle uses to find its own tag (script-config.ts)
3
+ const TC_EMAIL_SCRIPT = "script[src*='raisemore-email'], script[data-raisemore-email]";
4
+ const DEFAULT_RELAY_URL = "https://email-validator.4sitestudios.com";
5
+ const DEFAULT_VERSION = "v1";
6
+ export class TidyContactEmail {
7
+ constructor() {
8
+ this.logger = new EngridLogger("TidyContactEmail", "#FFFFFF", "#4d9068", "📧");
9
+ this.options = null;
10
+ const options = ENGrid.getOption("TidyContactEmail");
11
+ if (!options)
12
+ return;
13
+ this.options = options;
14
+ if (!this.shouldRun())
15
+ return;
16
+ this.loadScript();
17
+ }
18
+ shouldRun() {
19
+ var _a, _b;
20
+ if (!((_a = this.options) === null || _a === void 0 ? void 0 : _a.clientKey)) {
21
+ this.logger.danger("clientKey not set. TidyContact Email will not load.");
22
+ return false;
23
+ }
24
+ const searchParams = new URLSearchParams(window.location.search);
25
+ if (searchParams.has("bypassemailvalidation")) {
26
+ this.logger.log("Bypass Email Validation Enabled - not loading TidyContact Email");
27
+ return false;
28
+ }
29
+ const pageTypes = (_b = this.options.pageTypes) !== null && _b !== void 0 ? _b : [];
30
+ if (pageTypes.length > 0 &&
31
+ pageTypes.indexOf(ENGrid.getPageType()) === -1) {
32
+ this.logger.log("TidyContact Email is disabled on this page type");
33
+ return false;
34
+ }
35
+ if (!ENGrid.getField("supporter.emailAddress")) {
36
+ this.logger.log("E-mail Field Not Found");
37
+ return false;
38
+ }
39
+ if (ENGrid.getOption("NeverBounceAPI") ||
40
+ ENGrid.getOption("FreshAddress")) {
41
+ this.logger.danger("NeverBounce or FreshAddress is also enabled. Two email validators on one field is not supported, so TidyContact Email will not load.");
42
+ return false;
43
+ }
44
+ if (document.querySelector(TC_EMAIL_SCRIPT)) {
45
+ this.logger.log("TidyContact Email script already on the page (manual install). Not loading it again.");
46
+ return false;
47
+ }
48
+ return true;
49
+ }
50
+ loadScript() {
51
+ const options = this.options;
52
+ const relayUrl = (options.relayUrl || DEFAULT_RELAY_URL).replace(/\/+$/, "");
53
+ const script = document.createElement("script");
54
+ script.src =
55
+ options.scriptUrl ||
56
+ `${relayUrl}/embed/engrid/${options.version || DEFAULT_VERSION}/raisemore-email.js`;
57
+ script.setAttribute("data-raisemore-email", "");
58
+ script.setAttribute("data-relay-url", relayUrl);
59
+ script.setAttribute("data-client-key", options.clientKey);
60
+ // Only what the client set; everything else keeps TC Email's own defaults
61
+ const optional = [
62
+ ["timeout-ms", options.timeoutMs],
63
+ ["hard-block", options.hardBlock],
64
+ ["prefill-skip", options.prefillSkip],
65
+ ["en-recognition", options.enRecognition],
66
+ ];
67
+ optional.forEach(([name, value]) => {
68
+ if (value !== undefined && value !== null) {
69
+ script.setAttribute(`data-${name}`, String(value));
70
+ }
71
+ });
72
+ script.onload = () => {
73
+ ENGrid.setBodyData("tidycontact-email", "loaded");
74
+ this.logger.success(`Loaded ${script.src}`);
75
+ };
76
+ script.onerror = () => {
77
+ ENGrid.setBodyData("tidycontact-email", "error");
78
+ this.logger.danger(`Could not load ${script.src}. The form keeps working without email validation.`);
79
+ };
80
+ ENGrid.setBodyData("tidycontact-email", "loading");
81
+ document.body.appendChild(script);
82
+ }
83
+ }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const AppVersion = "0.28.5";
1
+ export declare const AppVersion = "0.28.7";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const AppVersion = "0.28.5";
1
+ export const AppVersion = "0.28.7";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@4site/engrid-scripts",
3
- "version": "0.28.5",
3
+ "version": "0.28.7",
4
4
  "description": "Scripts for the ENGRID Project",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -25,7 +25,7 @@
25
25
  "strongly-typed-events": "^2.0.9"
26
26
  },
27
27
  "homepage": "https://github.com/4site-interactive-studios/engrid#readme",
28
- "gitHead": "8151380d0dd8e669c29762358586e0d276988ced",
28
+ "gitHead": "91cc1bb42cdf7660319f912cb8937d37968d2324",
29
29
  "devDependencies": {
30
30
  "nodemon": "^2.0.20",
31
31
  "typescript": "^4.9.5"