@4site/engrid-scripts 0.24.3 → 0.24.5
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 +4 -1
- package/dist/auto-country-select.js +6 -1
- package/dist/data-layer.d.ts +1 -0
- package/dist/data-layer.js +29 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/interfaces/options.d.ts +6 -0
- package/dist/interfaces/options.js +3 -0
- package/dist/optin-ladder.d.ts +2 -1
- package/dist/optin-ladder.js +43 -20
- package/dist/sticky-nsg.d.ts +10 -0
- package/dist/sticky-nsg.js +109 -0
- package/dist/sticky-prepopulation.d.ts +17 -0
- package/dist/sticky-prepopulation.js +214 -0
- package/dist/swap-amounts.js +6 -1
- package/dist/tidycontact.d.ts +1 -0
- package/dist/tidycontact.js +12 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -2
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, 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, } from ".";
|
|
3
3
|
export class App extends ENGrid {
|
|
4
4
|
constructor(options) {
|
|
5
5
|
super();
|
|
@@ -160,6 +160,8 @@ export class App extends ENGrid {
|
|
|
160
160
|
new Autosubmit();
|
|
161
161
|
// Adjust display of event tickets.
|
|
162
162
|
new EventTickets();
|
|
163
|
+
// StickyNSG - Must load before SwapAmounts
|
|
164
|
+
new StickyNSG();
|
|
163
165
|
// Swap Amounts
|
|
164
166
|
new SwapAmounts();
|
|
165
167
|
// On the end of the script, after all subscribers defined, let's load the current frequency
|
|
@@ -279,6 +281,7 @@ export class App extends ENGrid {
|
|
|
279
281
|
new CheckboxLabel();
|
|
280
282
|
new PostDonationEmbed();
|
|
281
283
|
new FrequencyUpsell();
|
|
284
|
+
new StickyPrepopulation();
|
|
282
285
|
//Debug panel
|
|
283
286
|
let showDebugPanel = this.options.Debug;
|
|
284
287
|
try {
|
|
@@ -16,10 +16,15 @@ export class AutoCountrySelect {
|
|
|
16
16
|
ENGrid.getUrlParameter("supporter.region") ||
|
|
17
17
|
(ENGrid.getUrlParameter("ea.url.id") &&
|
|
18
18
|
!ENGrid.getUrlParameter("forwarded"));
|
|
19
|
+
// If fast form is active, then personal details have already been filled somehow and we should not override the country selection
|
|
20
|
+
// The client is also likely using WelcomeBack.
|
|
21
|
+
const fastFormActive = ENGrid.getBodyData("hide-fast-address-details") ||
|
|
22
|
+
ENGrid.getBodyData("hide-fast-personal-details");
|
|
19
23
|
if (!engridAutofill &&
|
|
20
24
|
!submissionFailed &&
|
|
21
25
|
hasIntlSupport &&
|
|
22
|
-
!locationDataInUrl
|
|
26
|
+
!locationDataInUrl &&
|
|
27
|
+
!fastFormActive) {
|
|
23
28
|
fetch(`https://${window.location.hostname}/cdn-cgi/trace`)
|
|
24
29
|
.then((res) => res.text())
|
|
25
30
|
.then((t) => {
|
package/dist/data-layer.d.ts
CHANGED
package/dist/data-layer.js
CHANGED
|
@@ -24,6 +24,19 @@ export class DataLayer {
|
|
|
24
24
|
this._form = EnForm.getInstance();
|
|
25
25
|
this.encoder = new TextEncoder();
|
|
26
26
|
this.endOfGiftProcessStorageKey = "ENGRID_END_OF_GIFT_PROCESS_EVENTS";
|
|
27
|
+
// pageJson entries related to the gift process
|
|
28
|
+
this.giftFields = [
|
|
29
|
+
"amount",
|
|
30
|
+
"currency",
|
|
31
|
+
"donationLogId",
|
|
32
|
+
"feeCover",
|
|
33
|
+
"giftProcess",
|
|
34
|
+
"paymentType",
|
|
35
|
+
"receiptNumber",
|
|
36
|
+
"recurring",
|
|
37
|
+
"transactionId",
|
|
38
|
+
"transactionType",
|
|
39
|
+
];
|
|
27
40
|
this.excludedFields = [
|
|
28
41
|
// Credit Card
|
|
29
42
|
"transaction.ccnumber",
|
|
@@ -102,13 +115,27 @@ export class DataLayer {
|
|
|
102
115
|
onLoad() {
|
|
103
116
|
// Collect all data layer variables to push at once
|
|
104
117
|
const dataLayerData = {};
|
|
118
|
+
const suppressEcardData = ENGrid.getPageType() === "ECARD" &&
|
|
119
|
+
ENGrid.getOption("SuppressPurchaseEcard");
|
|
105
120
|
if (ENGrid.getGiftProcess()) {
|
|
106
|
-
|
|
107
|
-
this
|
|
121
|
+
// EN will chain together gift process data on the page json when redirecting from a completed donation to an ecard.
|
|
122
|
+
// Since the ecard page can be embedded on the thank you page of a donation, this can cause confusion in the data layer with events
|
|
123
|
+
// firing for both the donation and the ecard on the same page.
|
|
124
|
+
if (suppressEcardData) {
|
|
125
|
+
this.logger.log("⛔ Gift process was detected BUT suppressing EN_SUCCESSFUL_DONATION event due to SuppressPurchaseEcard option enabled");
|
|
126
|
+
window.sessionStorage.removeItem(this.endOfGiftProcessStorageKey);
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.logger.log("EN_SUCCESSFUL_DONATION");
|
|
130
|
+
this.addEndOfGiftProcessEventsToDataLayer();
|
|
131
|
+
}
|
|
108
132
|
}
|
|
109
133
|
if (window.pageJson) {
|
|
110
134
|
const pageJson = window.pageJson;
|
|
111
135
|
for (const property in pageJson) {
|
|
136
|
+
if (suppressEcardData && this.giftFields.includes(property)) {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
112
139
|
const key = `EN_PAGEJSON_${property.toUpperCase()}`;
|
|
113
140
|
const value = pageJson[property];
|
|
114
141
|
dataLayerData[key] = this.transformJSON(value);
|
package/dist/index.d.ts
CHANGED
|
@@ -86,6 +86,8 @@ export * from "./optin-ladder";
|
|
|
86
86
|
export * from "./post-donation-embed";
|
|
87
87
|
export * from "./frequency-upsell-modal";
|
|
88
88
|
export * from "./frequency-upsell";
|
|
89
|
+
export * from "./sticky-nsg";
|
|
90
|
+
export * from "./sticky-prepopulation";
|
|
89
91
|
export * from "./preferred-payment-method";
|
|
90
92
|
export * from "./events";
|
|
91
93
|
export * from "./version";
|
package/dist/index.js
CHANGED
|
@@ -86,6 +86,8 @@ export * from "./optin-ladder";
|
|
|
86
86
|
export * from "./post-donation-embed";
|
|
87
87
|
export * from "./frequency-upsell-modal";
|
|
88
88
|
export * from "./frequency-upsell";
|
|
89
|
+
export * from "./sticky-nsg";
|
|
90
|
+
export * from "./sticky-prepopulation";
|
|
89
91
|
export * from "./preferred-payment-method";
|
|
90
92
|
// Events
|
|
91
93
|
export * from "./events";
|
|
@@ -18,6 +18,7 @@ export interface Options {
|
|
|
18
18
|
UseAmountValidatorFromEN?: boolean;
|
|
19
19
|
SkipToMainContentLink?: boolean;
|
|
20
20
|
SrcDefer?: boolean;
|
|
21
|
+
SuppressPurchaseEcard?: boolean;
|
|
21
22
|
NeverBounceAPI?: string | null;
|
|
22
23
|
NeverBounceDateField?: string | null;
|
|
23
24
|
NeverBounceDateFormat?: string;
|
|
@@ -50,8 +51,13 @@ export interface Options {
|
|
|
50
51
|
fieldClearSelectorTargetLocation?: string;
|
|
51
52
|
checked?: boolean;
|
|
52
53
|
};
|
|
54
|
+
StickyNSG?: boolean;
|
|
55
|
+
StickyPrepopulation?: false | {
|
|
56
|
+
fields: string[];
|
|
57
|
+
};
|
|
53
58
|
TidyContact?: false | {
|
|
54
59
|
cid?: string;
|
|
60
|
+
page_types?: ("DONATION" | "ECARD" | "SURVEY" | "EMAILTOTARGET" | "ADVOCACY" | "SUBSCRIBEFORM" | "EVENT" | "SUPPORTERHUB" | "UNSUBSCRIBE" | "TWEETPAGE" | "UNKNOWN")[];
|
|
55
61
|
record_field?: string;
|
|
56
62
|
date_field?: string;
|
|
57
63
|
status_field?: string;
|
|
@@ -17,6 +17,7 @@ export const OptionsDefaults = {
|
|
|
17
17
|
UseAmountValidatorFromEN: false,
|
|
18
18
|
SkipToMainContentLink: true,
|
|
19
19
|
SrcDefer: true,
|
|
20
|
+
SuppressPurchaseEcard: false,
|
|
20
21
|
NeverBounceAPI: null,
|
|
21
22
|
NeverBounceDateField: null,
|
|
22
23
|
NeverBounceStatusField: null,
|
|
@@ -41,6 +42,8 @@ export const OptionsDefaults = {
|
|
|
41
42
|
CountryRedirect: false,
|
|
42
43
|
WelcomeBack: false,
|
|
43
44
|
OptInLadder: false,
|
|
45
|
+
StickyNSG: false,
|
|
46
|
+
StickyPrepopulation: false,
|
|
44
47
|
PreferredPaymentMethod: false,
|
|
45
48
|
PageLayouts: [
|
|
46
49
|
"leftleft1col",
|
package/dist/optin-ladder.d.ts
CHANGED
|
@@ -7,9 +7,10 @@ export declare class OptInLadder {
|
|
|
7
7
|
private runAsChildThankYou;
|
|
8
8
|
private inIframe;
|
|
9
9
|
private saveStepToSessionStorage;
|
|
10
|
-
private getFirstPageUrl;
|
|
11
10
|
private saveOptInsToSessionStorage;
|
|
12
11
|
private isEmbeddedThankYouPage;
|
|
12
|
+
private getPageUrl;
|
|
13
|
+
private getFirstPageUrl;
|
|
13
14
|
private hidePage;
|
|
14
15
|
private clearSessionStorage;
|
|
15
16
|
}
|
package/dist/optin-ladder.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Docs: https://engrid.4sitestudios.com/component/optin-ladder
|
|
3
|
+
* This component is responsible for showing a ladder of checkboxes, one at a time, to the user.
|
|
4
|
+
* If the page is not embedded in an iframe, and there are EN's Opt-In fields on the page, we will store the values to sessionStorage upon Form Submit.
|
|
5
|
+
* If the page is embedded in an iframe and on a Thank You Page, we will look for .optin-ladder elements, compare the values to sessionStorage, and show the next checkbox in the ladder, removing all but the first match.
|
|
6
|
+
* If the page is embedded in an iframe and on a Thank You Page, and the child iFrame is also a Thank You Page, we will look for a sessionStorage that has the current ladder step and the total number of steps.
|
|
7
|
+
* If the current step is less than the total number of steps, we will redirect to the first page. If the current step is equal to the total number of steps, we will show the Thank You Page.
|
|
8
|
+
*/
|
|
6
9
|
import { EngridLogger, ENGrid, EnForm } from ".";
|
|
7
10
|
export class OptInLadder {
|
|
8
11
|
constructor() {
|
|
@@ -95,7 +98,7 @@ export class OptInLadder {
|
|
|
95
98
|
if (!emailField || !emailField.value) {
|
|
96
99
|
this.logger.log("Email field is empty");
|
|
97
100
|
// Since this is a OptInLadder page with no e-mail address, hide the page
|
|
98
|
-
this.hidePage();
|
|
101
|
+
this.hidePage(true);
|
|
99
102
|
return;
|
|
100
103
|
}
|
|
101
104
|
const sessionStorageCheckboxValues = JSON.parse(sessionStorage.getItem("engrid.supporter.questions") || "{}");
|
|
@@ -179,6 +182,12 @@ export class OptInLadder {
|
|
|
179
182
|
return;
|
|
180
183
|
}
|
|
181
184
|
const hasOptInLadderStop = sessionStorage.getItem("engrid.optin-ladder-stop");
|
|
185
|
+
const hasOptInLadderPersistStop = sessionStorage.getItem("engrid.optin-ladder-persist-stop");
|
|
186
|
+
if (hasOptInLadderPersistStop) {
|
|
187
|
+
this.logger.log("OptInLadder has been stopped with persist flag, showing the thank-you page");
|
|
188
|
+
sessionStorage.removeItem("engrid.optin-ladder-persist-stop");
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
182
191
|
if (hasOptInLadderStop) {
|
|
183
192
|
this.logger.log("OptInLadder has been stopped");
|
|
184
193
|
return;
|
|
@@ -186,9 +195,14 @@ export class OptInLadder {
|
|
|
186
195
|
const sessionStorageOptInLadder = JSON.parse(sessionStorage.getItem("engrid.optin-ladder") || "{}");
|
|
187
196
|
const currentStep = sessionStorageOptInLadder.step || 0;
|
|
188
197
|
const totalSteps = sessionStorageOptInLadder.totalSteps || 0;
|
|
189
|
-
if (
|
|
190
|
-
this.logger.log(
|
|
198
|
+
if (totalSteps === 0) {
|
|
199
|
+
this.logger.log("No total steps found in sessionStorage");
|
|
191
200
|
this.hidePage();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
else if (currentStep <= totalSteps) {
|
|
204
|
+
this.logger.log(`Current step ${currentStep} is less or equal to total steps ${totalSteps}`);
|
|
205
|
+
this.hidePage(true);
|
|
192
206
|
// Redirect to the first page
|
|
193
207
|
window.location.href = this.getFirstPageUrl();
|
|
194
208
|
return;
|
|
@@ -211,14 +225,6 @@ export class OptInLadder {
|
|
|
211
225
|
sessionStorage.setItem("engrid.optin-ladder", JSON.stringify({ step, totalSteps }));
|
|
212
226
|
this.logger.log(`Saved step ${step} of ${totalSteps} to sessionStorage`);
|
|
213
227
|
}
|
|
214
|
-
getFirstPageUrl() {
|
|
215
|
-
// Get the current URL and replace the last path with 1?chain
|
|
216
|
-
const url = new URL(window.location.href);
|
|
217
|
-
const path = url.pathname.split("/");
|
|
218
|
-
path.pop();
|
|
219
|
-
path.push("1");
|
|
220
|
-
return url.origin + path.join("/") + "?chain";
|
|
221
|
-
}
|
|
222
228
|
saveOptInsToSessionStorage(type = "parent") {
|
|
223
229
|
// Grab all the checkboxes with the name starting with "supporter.questions"
|
|
224
230
|
const checkboxes = document.querySelectorAll('input[name^="supporter.questions"]');
|
|
@@ -248,15 +254,32 @@ export class OptInLadder {
|
|
|
248
254
|
isEmbeddedThankYouPage() {
|
|
249
255
|
return ENGrid.getBodyData("embedded") === "thank-you-page-donation";
|
|
250
256
|
}
|
|
251
|
-
|
|
252
|
-
const
|
|
253
|
-
|
|
254
|
-
|
|
257
|
+
getPageUrl(page, chain = false) {
|
|
258
|
+
const url = new URL(window.location.href);
|
|
259
|
+
const path = url.pathname.split("/");
|
|
260
|
+
path[path.length - 1] = String(page);
|
|
261
|
+
return url.origin + path.join("/") + (chain ? "?chain" : "");
|
|
262
|
+
}
|
|
263
|
+
getFirstPageUrl() {
|
|
264
|
+
return this.getPageUrl(1, true);
|
|
265
|
+
}
|
|
266
|
+
hidePage(forceHide = false) {
|
|
267
|
+
if (ENGrid.getBodyData("opt-in-ladder-persist") === "true" && !forceHide) {
|
|
268
|
+
this.logger.log("Hide activated, but opt-in ladder persist is enabled, showing the thank-you page");
|
|
269
|
+
sessionStorage.setItem("engrid.optin-ladder-persist-stop", "Y");
|
|
270
|
+
window.location.href = this.getPageUrl(2);
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
const engridPage = document.querySelector("#engrid");
|
|
274
|
+
if (engridPage) {
|
|
275
|
+
engridPage.classList.add("hide");
|
|
276
|
+
}
|
|
255
277
|
}
|
|
256
278
|
}
|
|
257
279
|
clearSessionStorage() {
|
|
258
280
|
sessionStorage.removeItem("engrid.supporter.questions");
|
|
259
281
|
sessionStorage.removeItem("engrid.optin-ladder");
|
|
260
282
|
sessionStorage.removeItem("engrid.optin-ladder-stop");
|
|
283
|
+
sessionStorage.removeItem("engrid.optin-ladder-persist-stop");
|
|
261
284
|
}
|
|
262
285
|
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { EngridLogger } from "./logger";
|
|
2
|
+
import { ENGrid } from "./engrid";
|
|
3
|
+
import * as cookie from "./cookie";
|
|
4
|
+
export class StickyNSG {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.logger = new EngridLogger("StickyNSG", "teal", "white", "📌");
|
|
7
|
+
this.cookieName = "engrid-sticky-nsg";
|
|
8
|
+
if (!this.shouldRun())
|
|
9
|
+
return;
|
|
10
|
+
this.logger.log("Sticky NSG is enabled");
|
|
11
|
+
this.deleteCookieIfGiftProcessComplete();
|
|
12
|
+
this.createStickyNSGCookie();
|
|
13
|
+
this.applyStickyNSGCookie();
|
|
14
|
+
}
|
|
15
|
+
shouldRun() {
|
|
16
|
+
return ENGrid.getOption("StickyNSG") === true;
|
|
17
|
+
}
|
|
18
|
+
/*
|
|
19
|
+
* Determine if NSG provided by EN is active on the page
|
|
20
|
+
*/
|
|
21
|
+
nsgActiveOnPage() {
|
|
22
|
+
return (window.EngagingNetworks &&
|
|
23
|
+
window.EngagingNetworks.suggestedGift &&
|
|
24
|
+
typeof window.EngagingNetworks.suggestedGift === "object" &&
|
|
25
|
+
Object.keys(window.EngagingNetworks.suggestedGift).length > 0);
|
|
26
|
+
}
|
|
27
|
+
/*
|
|
28
|
+
* Delete the cookie if the gift process is complete
|
|
29
|
+
*/
|
|
30
|
+
deleteCookieIfGiftProcessComplete() {
|
|
31
|
+
if (ENGrid.getGiftProcess()) {
|
|
32
|
+
this.logger.log("Gift process complete, removing sticky NSG cookie if it exists");
|
|
33
|
+
cookie.remove(this.cookieName);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/*
|
|
37
|
+
* Create the sticky NSG cookie if NSG is active on the page
|
|
38
|
+
*/
|
|
39
|
+
createStickyNSGCookie() {
|
|
40
|
+
var _a, _b, _c, _d, _e, _f;
|
|
41
|
+
if (!this.nsgActiveOnPage()) {
|
|
42
|
+
this.logger.log("No NSG active on page, not creating sticky NSG cookie");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const url = new URL(window.location.href);
|
|
46
|
+
if (url.searchParams.get("skipstickynsg") === "true") {
|
|
47
|
+
this.logger.log("'skipstickynsg' param present, not creating sticky NSG cookie");
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// We do some reformating to match the EngridAmounts format
|
|
51
|
+
// We also add "Other" to the amounts list
|
|
52
|
+
const nsg = window.EngagingNetworks.suggestedGift;
|
|
53
|
+
this.logger.log("Creating sticky NSG cookie", nsg);
|
|
54
|
+
const oneTimeNsg = (_a = nsg.single) === null || _a === void 0 ? void 0 : _a.reduce((acc, curr) => {
|
|
55
|
+
acc[curr.value] = curr.value;
|
|
56
|
+
return acc;
|
|
57
|
+
}, {});
|
|
58
|
+
const oneTimeDefault = (_c = (_b = nsg.single) === null || _b === void 0 ? void 0 : _b.find((gift) => gift.nextSuggestedGift)) === null || _c === void 0 ? void 0 : _c.value;
|
|
59
|
+
const recurringNsg = (_d = nsg.recurring) === null || _d === void 0 ? void 0 : _d.reduce((acc, curr) => {
|
|
60
|
+
acc[curr.value] = curr.value;
|
|
61
|
+
return acc;
|
|
62
|
+
}, {});
|
|
63
|
+
const recurringDefault = (_f = (_e = nsg.recurring) === null || _e === void 0 ? void 0 : _e.find((gift) => gift.nextSuggestedGift)) === null || _f === void 0 ? void 0 : _f.value;
|
|
64
|
+
const nsgCookieData = {};
|
|
65
|
+
if (oneTimeNsg && oneTimeDefault) {
|
|
66
|
+
nsgCookieData.onetime = {
|
|
67
|
+
amounts: oneTimeNsg,
|
|
68
|
+
default: oneTimeDefault,
|
|
69
|
+
stickyDefault: false,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
if (recurringNsg && recurringDefault) {
|
|
73
|
+
nsgCookieData.monthly = {
|
|
74
|
+
amounts: recurringNsg,
|
|
75
|
+
default: recurringDefault,
|
|
76
|
+
stickyDefault: false,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
if (Object.keys(nsgCookieData).length === 0) {
|
|
80
|
+
this.logger.log("No valid NSG data found to create sticky NSG cookie");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const cookieValue = JSON.stringify(nsgCookieData);
|
|
84
|
+
cookie.set(this.cookieName, cookieValue, { path: "/", expires: 30 });
|
|
85
|
+
this.logger.log("Sticky NSG cookie created", cookieValue);
|
|
86
|
+
}
|
|
87
|
+
/*
|
|
88
|
+
* Apply the sticky NSG cookie values to window.EngridAmounts if NSG is not active on the page
|
|
89
|
+
*/
|
|
90
|
+
applyStickyNSGCookie() {
|
|
91
|
+
if (this.nsgActiveOnPage()) {
|
|
92
|
+
this.logger.log("NSG active on page, not applying sticky NSG cookie, leaving the EN NSG values.");
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const cookieValue = cookie.get(this.cookieName);
|
|
96
|
+
if (!cookieValue) {
|
|
97
|
+
this.logger.log("No sticky NSG cookie found, nothing to apply");
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
const nsg = JSON.parse(cookieValue);
|
|
102
|
+
this.logger.log("Applying sticky NSG cookie values", nsg);
|
|
103
|
+
window.EngridAmounts = nsg;
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
this.logger.error("Error parsing sticky NSG cookie, not applying", e);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class StickyPrepopulation {
|
|
2
|
+
private logger;
|
|
3
|
+
private options;
|
|
4
|
+
private cookieName;
|
|
5
|
+
constructor();
|
|
6
|
+
private shouldRun;
|
|
7
|
+
private deleteCookie;
|
|
8
|
+
private createCookie;
|
|
9
|
+
private applyPrepopulation;
|
|
10
|
+
private getSupporterDetailsFromFields;
|
|
11
|
+
private encryptSupporterDetails;
|
|
12
|
+
private decryptSupporterDetails;
|
|
13
|
+
private createEncryptionKey;
|
|
14
|
+
private arrayBufferToBase64;
|
|
15
|
+
private base64ToArrayBuffer;
|
|
16
|
+
private getSeed;
|
|
17
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { ENGrid } from "./engrid";
|
|
11
|
+
import { EngridLogger } from "./logger";
|
|
12
|
+
import * as cookie from "./cookie";
|
|
13
|
+
export class StickyPrepopulation {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.logger = new EngridLogger("StickyPrepopulation", "teal", "white", "📌");
|
|
16
|
+
this.options = { fields: [] };
|
|
17
|
+
this.cookieName = "engrid-sticky-prepop";
|
|
18
|
+
if (!this.shouldRun()) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.logger.log("StickyPrepopulation initialized");
|
|
22
|
+
if (ENGrid.getGiftProcess()) {
|
|
23
|
+
this.deleteCookie();
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (ENGrid.getPageNumber() !== 1 || !ENGrid.getField("supporter.emailAddress")) {
|
|
27
|
+
this.logger.log("Not on page 1 or email field not present, not creating cookie or applying pre-population.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.createCookie();
|
|
31
|
+
this.applyPrepopulation();
|
|
32
|
+
}
|
|
33
|
+
/*
|
|
34
|
+
* Determine if we should run the script
|
|
35
|
+
* Do not run if RememberMe is active
|
|
36
|
+
* Do not run if on a chain link
|
|
37
|
+
* Only run if StickyPrepopulation option is set with fields
|
|
38
|
+
*/
|
|
39
|
+
shouldRun() {
|
|
40
|
+
if (ENGrid.getOption("RememberMe")) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
const url = new URL(window.location.href);
|
|
44
|
+
const options = ENGrid.getOption("StickyPrepopulation");
|
|
45
|
+
if (options && (options === null || options === void 0 ? void 0 : options.fields.length) > 0 && !url.searchParams.has("chain")) {
|
|
46
|
+
this.options = options;
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/*
|
|
54
|
+
* Delete the cookie if the gift process is complete
|
|
55
|
+
*/
|
|
56
|
+
deleteCookie() {
|
|
57
|
+
this.logger.log("Gift process complete, removing sticky prepopulation cookie if it exists");
|
|
58
|
+
cookie.remove(this.cookieName);
|
|
59
|
+
}
|
|
60
|
+
/*
|
|
61
|
+
* Create the cookie if we're coming from a campaign link and supporterId is present
|
|
62
|
+
*/
|
|
63
|
+
createCookie() {
|
|
64
|
+
var _a;
|
|
65
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
+
// If we're not coming from a campaign link, don't create the cookie
|
|
67
|
+
if (!((_a = window.pageJson) === null || _a === void 0 ? void 0 : _a.supporterId)) {
|
|
68
|
+
this.logger.log("No supporterId present, not creating sticky prepopulation cookie");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const encryptedSupporterDetails = yield this.encryptSupporterDetails(this.getSupporterDetailsFromFields());
|
|
73
|
+
cookie.set(this.cookieName, window.btoa(JSON.stringify({
|
|
74
|
+
encryptedData: encryptedSupporterDetails.encryptedData,
|
|
75
|
+
iv: encryptedSupporterDetails.iv,
|
|
76
|
+
pageId: ENGrid.getPageID()
|
|
77
|
+
})), { path: "/", expires: 7 });
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
this.logger.log("Error creating sticky prepopulation cookie");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.logger.log("Sticky prepopulation cookie created");
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
/*
|
|
87
|
+
* If the cookie is present and supporterId is not (it's not a campaign link prefilled by EN),
|
|
88
|
+
* then apply the prepopulation
|
|
89
|
+
*/
|
|
90
|
+
applyPrepopulation() {
|
|
91
|
+
var _a;
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
const cookieData = cookie.get(this.cookieName);
|
|
94
|
+
if (!cookieData) {
|
|
95
|
+
this.logger.log("No sticky prepopulation cookie found, not prepopulating fields");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if ((_a = window.pageJson) === null || _a === void 0 ? void 0 : _a.supporterId) {
|
|
99
|
+
this.logger.log("SupporterId present, not applying sticky prepopulation");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
let supporterDetails = {};
|
|
103
|
+
try {
|
|
104
|
+
const encryptedSupporterDetails = JSON.parse(window.atob(cookieData));
|
|
105
|
+
if (!encryptedSupporterDetails || (encryptedSupporterDetails === null || encryptedSupporterDetails === void 0 ? void 0 : encryptedSupporterDetails.pageId) !== ENGrid.getPageID()) {
|
|
106
|
+
this.logger.log("No encrypted supporter details found in cookie, or page ID does not match");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
supporterDetails = JSON.parse(yield this.decryptSupporterDetails(this.base64ToArrayBuffer(encryptedSupporterDetails.encryptedData), new Uint8Array(this.base64ToArrayBuffer(encryptedSupporterDetails.iv))));
|
|
110
|
+
}
|
|
111
|
+
catch (e) {
|
|
112
|
+
this.logger.log("Error decrypting supporter details from cookie");
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
this.options.fields.forEach((fieldName) => {
|
|
116
|
+
if (!supporterDetails[fieldName])
|
|
117
|
+
return;
|
|
118
|
+
ENGrid.setFieldValue(fieldName, decodeURIComponent(supporterDetails[fieldName]));
|
|
119
|
+
this.logger.log(`Setting "${fieldName}" to "${decodeURIComponent(supporterDetails[fieldName])}"`);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
/*
|
|
124
|
+
* Get the supporter details from the form fields
|
|
125
|
+
*/
|
|
126
|
+
getSupporterDetailsFromFields() {
|
|
127
|
+
const supporterDetails = {};
|
|
128
|
+
this.options.fields.forEach((fieldName) => {
|
|
129
|
+
let field = document.querySelector(`[name="${fieldName}"]`);
|
|
130
|
+
// If it is a radio or checkbox, get the checked value
|
|
131
|
+
if (field) {
|
|
132
|
+
if (field.type === "radio" || field.type === "checkbox") {
|
|
133
|
+
field = document.querySelector(`[name="${fieldName}"]:checked`);
|
|
134
|
+
}
|
|
135
|
+
supporterDetails[fieldName] = encodeURIComponent(field.value);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
return supporterDetails;
|
|
139
|
+
}
|
|
140
|
+
/*
|
|
141
|
+
* Encrypt the supporter details
|
|
142
|
+
*/
|
|
143
|
+
encryptSupporterDetails(supporterDetails) {
|
|
144
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
145
|
+
const encryptionKey = yield this.createEncryptionKey(this.getSeed());
|
|
146
|
+
const iv = window.crypto.getRandomValues(new Uint8Array(12));
|
|
147
|
+
const supporterDetailsString = JSON.stringify(supporterDetails);
|
|
148
|
+
const encryptedData = yield window.crypto.subtle.encrypt({
|
|
149
|
+
name: "AES-GCM",
|
|
150
|
+
iv: iv,
|
|
151
|
+
}, encryptionKey, new TextEncoder().encode(supporterDetailsString));
|
|
152
|
+
return {
|
|
153
|
+
encryptedData: this.arrayBufferToBase64(encryptedData),
|
|
154
|
+
iv: this.arrayBufferToBase64(iv),
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/*
|
|
159
|
+
* Decrypt the supporter details
|
|
160
|
+
*/
|
|
161
|
+
decryptSupporterDetails(encryptedSupporterDetails, iv) {
|
|
162
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
const encryptionKey = yield this.createEncryptionKey(this.getSeed());
|
|
164
|
+
const decryptedData = yield window.crypto.subtle.decrypt({ name: "AES-GCM", iv: iv }, encryptionKey, encryptedSupporterDetails);
|
|
165
|
+
return new TextDecoder().decode(decryptedData);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
/*
|
|
169
|
+
* Create the encryption key
|
|
170
|
+
*/
|
|
171
|
+
createEncryptionKey(seed) {
|
|
172
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
173
|
+
const encoder = new TextEncoder();
|
|
174
|
+
const keyMaterial = yield window.crypto.subtle.importKey("raw", encoder.encode(seed), { name: "PBKDF2" }, false, ["deriveKey"]);
|
|
175
|
+
return yield window.crypto.subtle.deriveKey({
|
|
176
|
+
name: "PBKDF2",
|
|
177
|
+
salt: encoder.encode(seed),
|
|
178
|
+
iterations: 100000,
|
|
179
|
+
hash: "SHA-256",
|
|
180
|
+
}, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
/*
|
|
184
|
+
* Convert an ArrayBuffer to a base64 string
|
|
185
|
+
*/
|
|
186
|
+
arrayBufferToBase64(buffer) {
|
|
187
|
+
let binary = "";
|
|
188
|
+
const bytes = new Uint8Array(buffer);
|
|
189
|
+
const len = bytes.byteLength;
|
|
190
|
+
for (let i = 0; i < len; i++) {
|
|
191
|
+
binary += String.fromCharCode(bytes[i]);
|
|
192
|
+
}
|
|
193
|
+
return window.btoa(binary);
|
|
194
|
+
}
|
|
195
|
+
/*
|
|
196
|
+
* Create an Array Buffer from a base64 string
|
|
197
|
+
*/
|
|
198
|
+
base64ToArrayBuffer(base64) {
|
|
199
|
+
const binary_string = window.atob(base64);
|
|
200
|
+
const len = binary_string.length;
|
|
201
|
+
const bytes = new Uint8Array(len);
|
|
202
|
+
for (let i = 0; i < len; i++) {
|
|
203
|
+
bytes[i] = binary_string.charCodeAt(i);
|
|
204
|
+
}
|
|
205
|
+
return bytes.buffer;
|
|
206
|
+
}
|
|
207
|
+
/*
|
|
208
|
+
* Derive a seed from the page URL
|
|
209
|
+
*/
|
|
210
|
+
getSeed() {
|
|
211
|
+
const url = new URL(window.location.href);
|
|
212
|
+
return url.origin + url.pathname + (url.searchParams.get("ea.tracking.id") ? `?ea.tracking.id=${url.searchParams.get("ea.tracking.id")}` : '');
|
|
213
|
+
}
|
|
214
|
+
}
|
package/dist/swap-amounts.js
CHANGED
|
@@ -117,7 +117,12 @@ export class SwapAmounts {
|
|
|
117
117
|
}));
|
|
118
118
|
}
|
|
119
119
|
shouldRun() {
|
|
120
|
-
|
|
120
|
+
const hasNSG = window.EngagingNetworks.suggestedGift !== undefined &&
|
|
121
|
+
Object.keys(window.EngagingNetworks.suggestedGift).length > 0;
|
|
122
|
+
if (!!window.EngridAmounts && hasNSG) {
|
|
123
|
+
this.logger.log("Not swapping amounts because NSG is active on page");
|
|
124
|
+
}
|
|
125
|
+
return !!window.EngridAmounts && !hasNSG;
|
|
121
126
|
}
|
|
122
127
|
ignoreCurrentValue() {
|
|
123
128
|
const urlParam = ENGrid.getUrlParameter("transaction.donationAmt");
|
package/dist/tidycontact.d.ts
CHANGED
package/dist/tidycontact.js
CHANGED
|
@@ -268,6 +268,10 @@ export class TidyContact {
|
|
|
268
268
|
this.options = ENGrid.getOption("TidyContact");
|
|
269
269
|
if (this.options === false || !((_a = this.options) === null || _a === void 0 ? void 0 : _a.cid))
|
|
270
270
|
return;
|
|
271
|
+
if (!this.shouldRun()) {
|
|
272
|
+
this.logger.log("TidyContact is disabled on this page type");
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
271
275
|
this.loadOptions();
|
|
272
276
|
if (!this.hasAddressFields() && !this.phoneEnabled()) {
|
|
273
277
|
this.logger.log("No address fields found");
|
|
@@ -298,6 +302,14 @@ export class TidyContact {
|
|
|
298
302
|
}
|
|
299
303
|
}
|
|
300
304
|
}
|
|
305
|
+
shouldRun() {
|
|
306
|
+
if (this.options &&
|
|
307
|
+
this.options.page_types &&
|
|
308
|
+
this.options.page_types.length > 0) {
|
|
309
|
+
return this.options.page_types.includes(ENGrid.getPageType());
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
301
313
|
loadOptions() {
|
|
302
314
|
var _a, _b, _c, _d;
|
|
303
315
|
if (this.options) {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const AppVersion = "0.24.
|
|
1
|
+
export declare const AppVersion = "0.24.5";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const AppVersion = "0.24.
|
|
1
|
+
export const AppVersion = "0.24.5";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@4site/engrid-scripts",
|
|
3
|
-
"version": "0.24.
|
|
3
|
+
"version": "0.24.5",
|
|
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": "
|
|
28
|
+
"gitHead": "1db8b57a2a017c14aaa2f5704ee476be62df0970",
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"nodemon": "^2.0.20"
|
|
31
31
|
}
|