@4site/engrid-scripts 0.19.1
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/.prettierrc.js +226 -0
- package/LICENSE +24 -0
- package/dist/a11y.d.ts +6 -0
- package/dist/a11y.js +46 -0
- package/dist/add-name-to-message.d.ts +5 -0
- package/dist/add-name-to-message.js +49 -0
- package/dist/advocacy.d.ts +7 -0
- package/dist/advocacy.js +34 -0
- package/dist/amount-label.d.ts +6 -0
- package/dist/amount-label.js +29 -0
- package/dist/app.d.ts +19 -0
- package/dist/app.js +340 -0
- package/dist/apple-pay.d.ts +13 -0
- package/dist/apple-pay.js +169 -0
- package/dist/auto-country-select.d.ts +10 -0
- package/dist/auto-country-select.js +63 -0
- package/dist/auto-year.d.ts +7 -0
- package/dist/auto-year.js +35 -0
- package/dist/autocomplete.d.ts +5 -0
- package/dist/autocomplete.js +38 -0
- package/dist/autosubmit.d.ts +5 -0
- package/dist/autosubmit.js +14 -0
- package/dist/branding-html.d.ts +14 -0
- package/dist/branding-html.js +70 -0
- package/dist/capitalize-fields.d.ts +7 -0
- package/dist/capitalize-fields.js +22 -0
- package/dist/click-to-expand.d.ts +4 -0
- package/dist/click-to-expand.js +39 -0
- package/dist/cookie.d.ts +53 -0
- package/dist/cookie.js +76 -0
- package/dist/country-disable.d.ts +4 -0
- package/dist/country-disable.js +22 -0
- package/dist/country-redirect.d.ts +7 -0
- package/dist/country-redirect.js +61 -0
- package/dist/custom-currency.d.ts +9 -0
- package/dist/custom-currency.js +112 -0
- package/dist/data-attributes.d.ts +5 -0
- package/dist/data-attributes.js +122 -0
- package/dist/data-hide.d.ts +15 -0
- package/dist/data-hide.js +66 -0
- package/dist/data-layer.d.ts +23 -0
- package/dist/data-layer.js +312 -0
- package/dist/data-replace.d.ts +26 -0
- package/dist/data-replace.js +76 -0
- package/dist/debug-hidden-fields.d.ts +4 -0
- package/dist/debug-hidden-fields.js +42 -0
- package/dist/debug-panel.d.ts +27 -0
- package/dist/debug-panel.js +508 -0
- package/dist/deprecated.d.ts +5 -0
- package/dist/deprecated.js +40 -0
- package/dist/digital-wallets.d.ts +8 -0
- package/dist/digital-wallets.js +143 -0
- package/dist/ecard-to-target.d.ts +11 -0
- package/dist/ecard-to-target.js +73 -0
- package/dist/ecard.d.ts +8 -0
- package/dist/ecard.js +61 -0
- package/dist/embedded-ecard.d.ts +18 -0
- package/dist/embedded-ecard.js +267 -0
- package/dist/en-validators.d.ts +10 -0
- package/dist/en-validators.js +89 -0
- package/dist/engrid.d.ts +49 -0
- package/dist/engrid.js +547 -0
- package/dist/event-tickets.d.ts +3 -0
- package/dist/event-tickets.js +24 -0
- package/dist/events/country.d.ts +12 -0
- package/dist/events/country.js +42 -0
- package/dist/events/donation-amount.d.ts +16 -0
- package/dist/events/donation-amount.js +119 -0
- package/dist/events/donation-frequency.d.ts +17 -0
- package/dist/events/donation-frequency.js +115 -0
- package/dist/events/en-form.d.ts +20 -0
- package/dist/events/en-form.js +52 -0
- package/dist/events/index.d.ts +6 -0
- package/dist/events/index.js +6 -0
- package/dist/events/processing-fees.d.ts +20 -0
- package/dist/events/processing-fees.js +92 -0
- package/dist/events/remember-me-events.d.ts +18 -0
- package/dist/events/remember-me-events.js +36 -0
- package/dist/exit-intent-lightbox.d.ts +14 -0
- package/dist/exit-intent-lightbox.js +145 -0
- package/dist/expand-region-name.d.ts +7 -0
- package/dist/expand-region-name.js +44 -0
- package/dist/fast-form-fill.d.ts +8 -0
- package/dist/fast-form-fill.js +75 -0
- package/dist/freshaddress.d.ts +18 -0
- package/dist/freshaddress.js +204 -0
- package/dist/give-by-select.d.ts +9 -0
- package/dist/give-by-select.js +82 -0
- package/dist/iframe.d.ts +16 -0
- package/dist/iframe.js +217 -0
- package/dist/index.d.ts +82 -0
- package/dist/index.js +84 -0
- package/dist/input-has-value-and-focus.d.ts +9 -0
- package/dist/input-has-value-and-focus.js +50 -0
- package/dist/input-placeholders.d.ts +7 -0
- package/dist/input-placeholders.js +82 -0
- package/dist/interfaces/ecard-to-target-options.d.ts +9 -0
- package/dist/interfaces/ecard-to-target-options.js +8 -0
- package/dist/interfaces/embedded-ecard-options.d.ts +8 -0
- package/dist/interfaces/embedded-ecard-options.js +7 -0
- package/dist/interfaces/exit-intent-options.d.ts +13 -0
- package/dist/interfaces/exit-intent-options.js +13 -0
- package/dist/interfaces/options.d.ts +147 -0
- package/dist/interfaces/options.js +50 -0
- package/dist/interfaces/translate-options.d.ts +7 -0
- package/dist/interfaces/translate-options.js +42 -0
- package/dist/interfaces/upsell-options.d.ts +24 -0
- package/dist/interfaces/upsell-options.js +33 -0
- package/dist/live-currency.d.ts +15 -0
- package/dist/live-currency.js +140 -0
- package/dist/live-frequency.d.ts +13 -0
- package/dist/live-frequency.js +109 -0
- package/dist/live-variables.d.ts +21 -0
- package/dist/live-variables.js +147 -0
- package/dist/loader.d.ts +10 -0
- package/dist/loader.js +175 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.js +84 -0
- package/dist/media-attribution.d.ts +4 -0
- package/dist/media-attribution.js +66 -0
- package/dist/menu.d.ts +0 -0
- package/dist/menu.js +1 -0
- package/dist/min-max-amount.d.ts +13 -0
- package/dist/min-max-amount.js +71 -0
- package/dist/mobile-cta.d.ts +9 -0
- package/dist/mobile-cta.js +71 -0
- package/dist/modal.d.ts +19 -0
- package/dist/modal.js +129 -0
- package/dist/neverbounce.d.ts +23 -0
- package/dist/neverbounce.js +244 -0
- package/dist/other-amount.d.ts +6 -0
- package/dist/other-amount.js +70 -0
- package/dist/page-background.d.ts +7 -0
- package/dist/page-background.js +55 -0
- package/dist/plaid.d.ts +6 -0
- package/dist/plaid.js +49 -0
- package/dist/postal-code-validator.d.ts +20 -0
- package/dist/postal-code-validator.js +118 -0
- package/dist/premium-gift.d.ts +10 -0
- package/dist/premium-gift.js +115 -0
- package/dist/progress-bar.d.ts +3 -0
- package/dist/progress-bar.js +40 -0
- package/dist/remember-me.d.ts +61 -0
- package/dist/remember-me.js +358 -0
- package/dist/required-if-visible.d.ts +8 -0
- package/dist/required-if-visible.js +60 -0
- package/dist/set-attr.d.ts +4 -0
- package/dist/set-attr.js +31 -0
- package/dist/set-recurr-freq.d.ts +7 -0
- package/dist/set-recurr-freq.js +70 -0
- package/dist/show-hide-radio-checkboxes.d.ts +13 -0
- package/dist/show-hide-radio-checkboxes.js +161 -0
- package/dist/show-if-amount.d.ts +15 -0
- package/dist/show-if-amount.js +117 -0
- package/dist/show-if-present.d.ts +7 -0
- package/dist/show-if-present.js +79 -0
- package/dist/skip-link.d.ts +4 -0
- package/dist/skip-link.js +36 -0
- package/dist/src-defer.d.ts +6 -0
- package/dist/src-defer.js +70 -0
- package/dist/supporter-hub.d.ts +9 -0
- package/dist/supporter-hub.js +75 -0
- package/dist/swap-amounts.d.ts +45 -0
- package/dist/swap-amounts.js +81 -0
- package/dist/thank-you-page-conditional-content.d.ts +8 -0
- package/dist/thank-you-page-conditional-content.js +46 -0
- package/dist/ticker.d.ts +11 -0
- package/dist/ticker.js +66 -0
- package/dist/tidycontact.d.ts +46 -0
- package/dist/tidycontact.js +1202 -0
- package/dist/translate-fields.d.ts +12 -0
- package/dist/translate-fields.js +548 -0
- package/dist/universal-opt-in.d.ts +7 -0
- package/dist/universal-opt-in.js +91 -0
- package/dist/upsell-lightbox.d.ts +31 -0
- package/dist/upsell-lightbox.js +363 -0
- package/dist/url-params-to-body-attrs.d.ts +5 -0
- package/dist/url-params-to-body-attrs.js +14 -0
- package/dist/url-to-form.d.ts +7 -0
- package/dist/url-to-form.js +32 -0
- package/dist/us-only-form.d.ts +4 -0
- package/dist/us-only-form.js +30 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/dist/vgs.d.ts +16 -0
- package/dist/vgs.js +250 -0
- package/dist/welcome-back.d.ts +10 -0
- package/dist/welcome-back.js +112 -0
- package/package.json +32 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { ENGrid, EngridLogger, ExitIntentOptionsDefaults, } from ".";
|
|
2
|
+
import { get as getCookie, set as setCookie } from "./cookie";
|
|
3
|
+
export class ExitIntentLightbox {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.opened = false;
|
|
6
|
+
this.dataLayer = window.dataLayer || [];
|
|
7
|
+
this.logger = new EngridLogger("ExitIntentLightbox", "yellow", "black", "🚪");
|
|
8
|
+
this.triggerDelay = 1000; // Don't run the exit intent lightbox until at least 1 second has passed after page load
|
|
9
|
+
this.triggerTimeout = null;
|
|
10
|
+
let options = "EngridExitIntent" in window ? window.EngridExitIntent : {};
|
|
11
|
+
this.options = Object.assign(Object.assign({}, ExitIntentOptionsDefaults), options);
|
|
12
|
+
if (!this.options.enabled) {
|
|
13
|
+
this.logger.log("Not enabled");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (getCookie(this.options.cookieName)) {
|
|
17
|
+
this.logger.log("Not showing - cookie found.");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const activeTriggers = Object.keys(this.options.triggers)
|
|
21
|
+
.filter((t) => this.options.triggers[t])
|
|
22
|
+
.join(", ");
|
|
23
|
+
this.logger.log("Enabled, waiting for trigger. Active triggers: " + activeTriggers);
|
|
24
|
+
this.watchForTriggers();
|
|
25
|
+
}
|
|
26
|
+
watchForTriggers() {
|
|
27
|
+
window.addEventListener("load", () => {
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
if (this.options.triggers.mousePosition) {
|
|
30
|
+
this.watchMouse();
|
|
31
|
+
}
|
|
32
|
+
if (this.options.triggers.visibilityState) {
|
|
33
|
+
this.watchDocumentVisibility();
|
|
34
|
+
}
|
|
35
|
+
}, this.triggerDelay); // Delay activation of triggers
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
watchMouse() {
|
|
39
|
+
document.addEventListener("mouseout", (e) => {
|
|
40
|
+
// If this is an autocomplete element.
|
|
41
|
+
if (e.target.tagName.toLowerCase() == "input")
|
|
42
|
+
return;
|
|
43
|
+
// Get the current viewport width.
|
|
44
|
+
const vpWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
|
|
45
|
+
// If the current mouse X position is within 50px of the right edge
|
|
46
|
+
// of the viewport, return.
|
|
47
|
+
if (e.clientX >= vpWidth - 50)
|
|
48
|
+
return;
|
|
49
|
+
// If the current mouse Y position is not within 50px of the top
|
|
50
|
+
// edge of the viewport, return.
|
|
51
|
+
if (e.clientY >= 50)
|
|
52
|
+
return;
|
|
53
|
+
// Reliable, works on mouse exiting window and
|
|
54
|
+
// user switching active program
|
|
55
|
+
const from = e.relatedTarget;
|
|
56
|
+
if (!from) {
|
|
57
|
+
this.logger.log("Triggered by mouse position");
|
|
58
|
+
this.open();
|
|
59
|
+
}
|
|
60
|
+
if (!this.triggerTimeout) {
|
|
61
|
+
this.triggerTimeout = window.setTimeout(() => {
|
|
62
|
+
if (!from) {
|
|
63
|
+
this.logger.log("Triggered by mouse position");
|
|
64
|
+
this.open();
|
|
65
|
+
}
|
|
66
|
+
this.triggerTimeout = null;
|
|
67
|
+
}, this.triggerDelay);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
watchDocumentVisibility() {
|
|
72
|
+
const visibilityListener = () => {
|
|
73
|
+
if (document.visibilityState === "hidden") {
|
|
74
|
+
if (!this.triggerTimeout) {
|
|
75
|
+
this.triggerTimeout = window.setTimeout(() => {
|
|
76
|
+
this.logger.log("Triggered by visibilityState is hidden");
|
|
77
|
+
this.open();
|
|
78
|
+
document.removeEventListener("visibilitychange", visibilityListener);
|
|
79
|
+
this.triggerTimeout = null;
|
|
80
|
+
}, this.triggerDelay);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
document.addEventListener("visibilitychange", visibilityListener);
|
|
85
|
+
}
|
|
86
|
+
open() {
|
|
87
|
+
var _a, _b, _c;
|
|
88
|
+
if (this.opened)
|
|
89
|
+
return;
|
|
90
|
+
ENGrid.setBodyData("exit-intent-lightbox", "open");
|
|
91
|
+
setCookie(this.options.cookieName, "1", {
|
|
92
|
+
expires: this.options.cookieDuration,
|
|
93
|
+
});
|
|
94
|
+
document.body.insertAdjacentHTML("beforeend", `
|
|
95
|
+
<div class="ExitIntent">
|
|
96
|
+
<div class="ExitIntent__overlay">
|
|
97
|
+
<div class="ExitIntent__container">
|
|
98
|
+
<div class="ExitIntent__close">X</div>
|
|
99
|
+
<div class="ExitIntent__body">
|
|
100
|
+
<h2>${this.options.title}</h2>
|
|
101
|
+
<p>${this.options.text}</p>
|
|
102
|
+
<button type="button" class="ExitIntent__button">
|
|
103
|
+
${this.options.buttonText}
|
|
104
|
+
</button>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
`);
|
|
110
|
+
this.opened = true;
|
|
111
|
+
this.dataLayer.push({ event: "exit_intent_lightbox_shown" });
|
|
112
|
+
(_a = document
|
|
113
|
+
.querySelector(".ExitIntent__close")) === null || _a === void 0 ? void 0 : _a.addEventListener("click", () => {
|
|
114
|
+
this.dataLayer.push({ event: "exit_intent_lightbox_closed" });
|
|
115
|
+
this.close();
|
|
116
|
+
});
|
|
117
|
+
(_b = document
|
|
118
|
+
.querySelector(".ExitIntent__overlay")) === null || _b === void 0 ? void 0 : _b.addEventListener("click", (event) => {
|
|
119
|
+
if (event.target === event.currentTarget) {
|
|
120
|
+
this.dataLayer.push({ event: "exit_intent_lightbox_closed" });
|
|
121
|
+
this.close();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
(_c = document
|
|
125
|
+
.querySelector(".ExitIntent__button")) === null || _c === void 0 ? void 0 : _c.addEventListener("click", () => {
|
|
126
|
+
this.dataLayer.push({ event: "exit_intent_lightbox_cta_clicked" });
|
|
127
|
+
this.close();
|
|
128
|
+
const target = this.options.buttonLink;
|
|
129
|
+
if (target.startsWith(".") || target.startsWith("#")) {
|
|
130
|
+
const targetEl = document.querySelector(target);
|
|
131
|
+
if (targetEl) {
|
|
132
|
+
targetEl.scrollIntoView({ behavior: "smooth" });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
window.open(target, "_blank");
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
close() {
|
|
141
|
+
var _a;
|
|
142
|
+
(_a = document.querySelector(".ExitIntent")) === null || _a === void 0 ? void 0 : _a.remove();
|
|
143
|
+
ENGrid.setBodyData("exit-intent-lightbox", "closed");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Populates hidden supporter field "Region Long Format" with expanded name (e.g FL becomes Florida)
|
|
2
|
+
import { ENGrid, EngridLogger } from ".";
|
|
3
|
+
import { EnForm } from "./events";
|
|
4
|
+
export class ExpandRegionName {
|
|
5
|
+
constructor() {
|
|
6
|
+
this._form = EnForm.getInstance();
|
|
7
|
+
this.logger = new EngridLogger("ExpandRegionName", "#333333", "#00eb65", "🌍");
|
|
8
|
+
if (this.shouldRun()) {
|
|
9
|
+
const expandedRegionField = ENGrid.getOption("RegionLongFormat");
|
|
10
|
+
console.log("expandedRegionField", expandedRegionField);
|
|
11
|
+
const hiddenRegion = document.querySelector(`[name="${expandedRegionField}"]`);
|
|
12
|
+
if (!hiddenRegion) {
|
|
13
|
+
this.logger.log(`CREATED field ${expandedRegionField}`);
|
|
14
|
+
ENGrid.createHiddenInput(expandedRegionField);
|
|
15
|
+
}
|
|
16
|
+
this._form.onValidate.subscribe(() => this.expandRegion());
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
shouldRun() {
|
|
20
|
+
return !!ENGrid.getOption("RegionLongFormat");
|
|
21
|
+
}
|
|
22
|
+
expandRegion() {
|
|
23
|
+
if (!this._form.validate)
|
|
24
|
+
return;
|
|
25
|
+
const userRegion = document.querySelector('[name="supporter.region"]'); // User entered region on the page
|
|
26
|
+
const expandedRegionField = ENGrid.getOption("RegionLongFormat");
|
|
27
|
+
const hiddenRegion = document.querySelector(`[name="${expandedRegionField}"]`); // Hidden region long form field
|
|
28
|
+
if (!userRegion) {
|
|
29
|
+
this.logger.log("No region field to populate the hidden region field with");
|
|
30
|
+
return; // Don't populate hidden region field if user region field isn't on page
|
|
31
|
+
}
|
|
32
|
+
if (userRegion.tagName === "SELECT" && "options" in userRegion) {
|
|
33
|
+
const regionValue = userRegion.options[userRegion.selectedIndex].innerText;
|
|
34
|
+
hiddenRegion.value = regionValue;
|
|
35
|
+
this.logger.log("Populated field", hiddenRegion.value);
|
|
36
|
+
}
|
|
37
|
+
else if (userRegion.tagName === "INPUT") {
|
|
38
|
+
const regionValue = userRegion.value;
|
|
39
|
+
hiddenRegion.value = regionValue;
|
|
40
|
+
this.logger.log("Populated field", hiddenRegion.value);
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This class adds body data attributes if all mandatory inputs, on specific form blocks, are filled.
|
|
3
|
+
* Related styling (to hide elements) can be found in "fast-form-fill.scss".
|
|
4
|
+
*
|
|
5
|
+
* To activate: add the custom class "fast-personal-details" or "fast-address-details"
|
|
6
|
+
* to the relevant form block.
|
|
7
|
+
*/
|
|
8
|
+
import { ENGrid, EngridLogger, RememberMeEvents } from ".";
|
|
9
|
+
export class FastFormFill {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.logger = new EngridLogger("FastFormFill", "white", "magenta", "📌");
|
|
12
|
+
this.rememberMeEvents = RememberMeEvents.getInstance();
|
|
13
|
+
if (ENGrid.getOption("RememberMe")) {
|
|
14
|
+
this.rememberMeEvents.onLoad.subscribe((hasData) => {
|
|
15
|
+
this.logger.log("Remember me - onLoad", hasData);
|
|
16
|
+
this.run();
|
|
17
|
+
});
|
|
18
|
+
this.rememberMeEvents.onClear.subscribe(() => {
|
|
19
|
+
// This is a test for the onClear event
|
|
20
|
+
this.logger.log("Remember me - onClear");
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
this.run();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
run() {
|
|
28
|
+
const fastPersonalDetailsFormBlocks = document.querySelectorAll(".en__component--formblock.fast-personal-details");
|
|
29
|
+
if (fastPersonalDetailsFormBlocks.length > 0) {
|
|
30
|
+
if ([...fastPersonalDetailsFormBlocks].every((formBlock) => FastFormFill.allMandatoryInputsAreFilled(formBlock))) {
|
|
31
|
+
this.logger.log("Personal details - All mandatory inputs are filled");
|
|
32
|
+
ENGrid.setBodyData("hide-fast-personal-details", "true");
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
this.logger.log("Personal details - Not all mandatory inputs are filled");
|
|
36
|
+
ENGrid.setBodyData("hide-fast-personal-details", "false");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const fastAddressDetailsFormBlocks = document.querySelectorAll(".en__component--formblock.fast-address-details");
|
|
40
|
+
if (fastAddressDetailsFormBlocks.length > 0) {
|
|
41
|
+
if ([...fastAddressDetailsFormBlocks].every((formBlock) => FastFormFill.allMandatoryInputsAreFilled(formBlock))) {
|
|
42
|
+
this.logger.log("Address details - All mandatory inputs are filled");
|
|
43
|
+
ENGrid.setBodyData("hide-fast-address-details", "true");
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.logger.log("Address details - Not all mandatory inputs are filled");
|
|
47
|
+
ENGrid.setBodyData("hide-fast-address-details", "false");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
static allMandatoryInputsAreFilled(formBlock) {
|
|
52
|
+
const fields = formBlock.querySelectorAll(".en__mandatory input, .en__mandatory select, .en__mandatory textarea");
|
|
53
|
+
return [...fields].every((input) => {
|
|
54
|
+
if (input.type === "radio" || input.type === "checkbox") {
|
|
55
|
+
const inputs = document.querySelectorAll('[name="' + input.name + '"]');
|
|
56
|
+
return [...inputs].some((radioOrCheckbox) => radioOrCheckbox.checked);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return input.value !== null && input.value.trim() !== "";
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
static someMandatoryInputsAreFilled(formBlock) {
|
|
64
|
+
const fields = formBlock.querySelectorAll(".en__mandatory input, .en__mandatory select, .en__mandatory textarea");
|
|
65
|
+
return [...fields].some((input) => {
|
|
66
|
+
if (input.type === "radio" || input.type === "checkbox") {
|
|
67
|
+
const inputs = document.querySelectorAll('[name="' + input.name + '"]');
|
|
68
|
+
return [...inputs].some((radioOrCheckbox) => radioOrCheckbox.checked);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
return input.value !== null && input.value.trim() !== "";
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class FreshAddress {
|
|
2
|
+
private form;
|
|
3
|
+
private emailField;
|
|
4
|
+
private emailWrapper;
|
|
5
|
+
private faDate;
|
|
6
|
+
private faStatus;
|
|
7
|
+
private faMessage;
|
|
8
|
+
private logger;
|
|
9
|
+
private shouldRun;
|
|
10
|
+
private options;
|
|
11
|
+
constructor();
|
|
12
|
+
private createFields;
|
|
13
|
+
private writeToFields;
|
|
14
|
+
private addEventListeners;
|
|
15
|
+
private callAPI;
|
|
16
|
+
private validateResponse;
|
|
17
|
+
private validate;
|
|
18
|
+
}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
// According to the FreshAddress documentation, you need to add the following code to your page:
|
|
2
|
+
// jQuery library.
|
|
3
|
+
// <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
|
|
4
|
+
// FreshAddress client-side integration library
|
|
5
|
+
// <script src="//api.freshaddress.biz/js/lib/freshaddress-client-7.0.min.js?token=[TOKEN HERE]"></script>
|
|
6
|
+
//
|
|
7
|
+
// I know. jQuery. But it's not my fault. It's FreshAddress's fault.
|
|
8
|
+
import { ENGrid, EngridLogger } from ".";
|
|
9
|
+
import { EnForm } from "./events";
|
|
10
|
+
export class FreshAddress {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.form = EnForm.getInstance();
|
|
13
|
+
this.emailField = null;
|
|
14
|
+
this.emailWrapper = document.querySelector(".en__field--emailAddress");
|
|
15
|
+
this.faDate = null;
|
|
16
|
+
this.faStatus = null;
|
|
17
|
+
this.faMessage = null;
|
|
18
|
+
this.logger = new EngridLogger("FreshAddress", "#039bc4", "#dfdfdf", "📧");
|
|
19
|
+
this.shouldRun = true;
|
|
20
|
+
this.options = ENGrid.getOption("FreshAddress");
|
|
21
|
+
if (this.options === false || !window.FreshAddress)
|
|
22
|
+
return;
|
|
23
|
+
this.emailField = document.getElementById("en__field_supporter_emailAddress");
|
|
24
|
+
if (this.emailField) {
|
|
25
|
+
this.createFields();
|
|
26
|
+
this.addEventListeners();
|
|
27
|
+
window.FreshAddressStatus = "idle";
|
|
28
|
+
if (this.emailField.value) {
|
|
29
|
+
this.logger.log("E-mail Field Found");
|
|
30
|
+
this.shouldRun = false;
|
|
31
|
+
}
|
|
32
|
+
window.setTimeout(() => {
|
|
33
|
+
if (this.emailField && this.emailField.value) {
|
|
34
|
+
this.logger.log("E-mail Filled Programatically");
|
|
35
|
+
this.shouldRun = false;
|
|
36
|
+
}
|
|
37
|
+
}, 1000);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.logger.log("E-mail Field Not Found");
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
createFields() {
|
|
44
|
+
if (!this.options)
|
|
45
|
+
return;
|
|
46
|
+
this.options.dateField = this.options.dateField || "fa_date";
|
|
47
|
+
this.faDate = ENGrid.getField(this.options.dateField);
|
|
48
|
+
if (!this.faDate) {
|
|
49
|
+
this.logger.log("Date Field Not Found. Creating...");
|
|
50
|
+
ENGrid.createHiddenInput(this.options.dateField, "");
|
|
51
|
+
this.faDate = ENGrid.getField(this.options.dateField);
|
|
52
|
+
}
|
|
53
|
+
this.options.statusField = this.options.statusField || "fa_status";
|
|
54
|
+
this.faStatus = ENGrid.getField(this.options.statusField);
|
|
55
|
+
if (!this.faStatus) {
|
|
56
|
+
this.logger.log("Status Field Not Found. Creating...");
|
|
57
|
+
ENGrid.createHiddenInput(this.options.statusField, "");
|
|
58
|
+
this.faStatus = ENGrid.getField(this.options.statusField);
|
|
59
|
+
}
|
|
60
|
+
this.options.messageField = this.options.messageField || "fa_message";
|
|
61
|
+
this.faMessage = ENGrid.getField(this.options.messageField);
|
|
62
|
+
if (!this.faMessage) {
|
|
63
|
+
this.logger.log("Message Field Not Found. Creating...");
|
|
64
|
+
ENGrid.createHiddenInput(this.options.messageField, "");
|
|
65
|
+
this.faMessage = ENGrid.getField(this.options.messageField);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
writeToFields(status, message) {
|
|
69
|
+
if (!this.options)
|
|
70
|
+
return;
|
|
71
|
+
this.faDate.value = ENGrid.formatDate(new Date(), this.options.dateFieldFormat || "yyyy-MM-dd");
|
|
72
|
+
this.faStatus.value = status;
|
|
73
|
+
this.faMessage.value = message;
|
|
74
|
+
this.emailWrapper.dataset.freshaddressSafetosendstatus =
|
|
75
|
+
status.toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
addEventListeners() {
|
|
78
|
+
var _a;
|
|
79
|
+
if (!this.options)
|
|
80
|
+
return;
|
|
81
|
+
// Add event listeners to fields
|
|
82
|
+
(_a = this.emailField) === null || _a === void 0 ? void 0 : _a.addEventListener("change", () => {
|
|
83
|
+
var _a, _b;
|
|
84
|
+
if (!this.shouldRun ||
|
|
85
|
+
((_a = this.emailField) === null || _a === void 0 ? void 0 : _a.value.includes("@4sitestudios.com"))) {
|
|
86
|
+
ENGrid.removeError(this.emailWrapper);
|
|
87
|
+
this.writeToFields("Valid", "Skipped");
|
|
88
|
+
this.logger.log("Skipping E-mail Validation");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
this.logger.log("Validating " + ((_b = this.emailField) === null || _b === void 0 ? void 0 : _b.value));
|
|
92
|
+
this.callAPI();
|
|
93
|
+
});
|
|
94
|
+
// Add event listener to submit
|
|
95
|
+
this.form.onValidate.subscribe(this.validate.bind(this));
|
|
96
|
+
}
|
|
97
|
+
callAPI() {
|
|
98
|
+
var _a;
|
|
99
|
+
if (!this.options || !window.FreshAddress)
|
|
100
|
+
return;
|
|
101
|
+
if (!this.shouldRun)
|
|
102
|
+
return;
|
|
103
|
+
window.FreshAddressStatus = "validating";
|
|
104
|
+
const email = (_a = this.emailField) === null || _a === void 0 ? void 0 : _a.value;
|
|
105
|
+
const options = { emps: false, rtc_timeout: 1200 };
|
|
106
|
+
const ret = window.FreshAddress.validateEmail(email, options).then((response) => {
|
|
107
|
+
this.logger.log("Validate API Response", JSON.parse(JSON.stringify(response)));
|
|
108
|
+
return this.validateResponse(response);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
validateResponse(data) {
|
|
112
|
+
var _a;
|
|
113
|
+
/* ERROR HANDLING: Let through in case of a service error. Enable form submission. */
|
|
114
|
+
if (data.isServiceError()) {
|
|
115
|
+
this.logger.log("Service Error");
|
|
116
|
+
this.writeToFields("Service Error", data.getErrorResponse());
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
/* CHECK RESULT: */
|
|
120
|
+
if (data.isValid()) {
|
|
121
|
+
// Set response message. No action required.
|
|
122
|
+
this.writeToFields("Valid", data.getComment());
|
|
123
|
+
ENGrid.removeError(this.emailWrapper);
|
|
124
|
+
if (data.hasSuggest()) {
|
|
125
|
+
// Valid, with Suggestion
|
|
126
|
+
ENGrid.setError(this.emailWrapper, `Did you mean ${data.getSuggEmail()}?`);
|
|
127
|
+
this.emailField.value = data.getSuggEmail();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else if (data.isError()) {
|
|
131
|
+
// Error Condition 1 - the service should always respond with finding E/W/V
|
|
132
|
+
this.writeToFields("Invalid", data.getErrorResponse());
|
|
133
|
+
ENGrid.setError(this.emailWrapper, data.getErrorResponse());
|
|
134
|
+
(_a = this.emailField) === null || _a === void 0 ? void 0 : _a.focus();
|
|
135
|
+
if (data.hasSuggest()) {
|
|
136
|
+
// Error, with Suggestion
|
|
137
|
+
ENGrid.setError(this.emailWrapper, `Did you mean ${data.getSuggEmail()}?`);
|
|
138
|
+
this.emailField.value = data.getSuggEmail();
|
|
139
|
+
this.writeToFields("Error", data.getErrorResponse());
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (data.isWarning()) {
|
|
143
|
+
this.writeToFields("Invalid", data.getErrorResponse());
|
|
144
|
+
ENGrid.setError(this.emailWrapper, data.getErrorResponse());
|
|
145
|
+
if (data.hasSuggest()) {
|
|
146
|
+
// Warning, with Suggestion
|
|
147
|
+
ENGrid.setError(this.emailWrapper, `Did you mean ${data.getSuggEmail()}?`);
|
|
148
|
+
this.emailField.value = data.getSuggEmail();
|
|
149
|
+
this.writeToFields("Warning", data.getErrorResponse());
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Error Condition 2 - the service should always respond with finding E/W/V
|
|
154
|
+
this.writeToFields("API Error", "Unknown Error");
|
|
155
|
+
}
|
|
156
|
+
window.FreshAddressStatus = "idle";
|
|
157
|
+
ENGrid.enableSubmit();
|
|
158
|
+
}
|
|
159
|
+
validate() {
|
|
160
|
+
var _a;
|
|
161
|
+
ENGrid.removeError(this.emailWrapper);
|
|
162
|
+
if (!this.form.validate)
|
|
163
|
+
return;
|
|
164
|
+
if (!this.options) {
|
|
165
|
+
this.form.validate = true;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
if (!this.shouldRun) {
|
|
169
|
+
this.form.validate = true;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (window.FreshAddressStatus === "validating") {
|
|
173
|
+
this.logger.log("Waiting for API Response");
|
|
174
|
+
// Self resolving Promise that waits 1000ms
|
|
175
|
+
const wait = new Promise((resolve, reject) => {
|
|
176
|
+
setTimeout(() => {
|
|
177
|
+
var _a;
|
|
178
|
+
const status = this.faStatus.value;
|
|
179
|
+
if (status === "" || status === "Invalid") {
|
|
180
|
+
this.logger.log("Promise Rejected");
|
|
181
|
+
(_a = this.emailField) === null || _a === void 0 ? void 0 : _a.focus();
|
|
182
|
+
reject(false);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
this.logger.log("Promise Resolved");
|
|
186
|
+
resolve(true);
|
|
187
|
+
}, 700);
|
|
188
|
+
});
|
|
189
|
+
this.form.validatePromise = wait;
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
else if (this.faStatus.value === "Invalid") {
|
|
193
|
+
this.form.validate = false;
|
|
194
|
+
window.setTimeout(() => {
|
|
195
|
+
ENGrid.setError(this.emailWrapper, this.faMessage.value);
|
|
196
|
+
}, 100);
|
|
197
|
+
(_a = this.emailField) === null || _a === void 0 ? void 0 : _a.focus();
|
|
198
|
+
ENGrid.enableSubmit();
|
|
199
|
+
return false;
|
|
200
|
+
}
|
|
201
|
+
this.form.validate = true;
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { ENGrid, EngridLogger, DonationFrequency } from ".";
|
|
2
|
+
export class GiveBySelect {
|
|
3
|
+
constructor() {
|
|
4
|
+
this.logger = new EngridLogger("GiveBySelect", "#FFF", "#333", "🐇");
|
|
5
|
+
this.transactionGiveBySelect = document.getElementsByName("transaction.giveBySelect");
|
|
6
|
+
this.paymentTypeField = document.querySelector("select[name='transaction.paymenttype']");
|
|
7
|
+
this._frequency = DonationFrequency.getInstance();
|
|
8
|
+
if (!this.transactionGiveBySelect)
|
|
9
|
+
return;
|
|
10
|
+
this._frequency.onFrequencyChange.subscribe(() => this.checkPaymentTypeVisibility());
|
|
11
|
+
this.transactionGiveBySelect.forEach((giveBySelect) => {
|
|
12
|
+
giveBySelect.addEventListener("change", () => {
|
|
13
|
+
this.logger.log("Changed to " + giveBySelect.value);
|
|
14
|
+
ENGrid.setPaymentType(giveBySelect.value);
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
// Set the initial value of giveBySelect to the transaction.paymenttype field
|
|
18
|
+
const paymentType = ENGrid.getPaymentType();
|
|
19
|
+
if (paymentType) {
|
|
20
|
+
this.logger.log("Setting giveBySelect to " + paymentType);
|
|
21
|
+
const isCard = [
|
|
22
|
+
"card",
|
|
23
|
+
"visa",
|
|
24
|
+
"mastercard",
|
|
25
|
+
"amex",
|
|
26
|
+
"discover",
|
|
27
|
+
"diners",
|
|
28
|
+
"jcb",
|
|
29
|
+
"vi",
|
|
30
|
+
"mc",
|
|
31
|
+
"ax",
|
|
32
|
+
"dc",
|
|
33
|
+
"di",
|
|
34
|
+
"jc",
|
|
35
|
+
].includes(paymentType.toLowerCase());
|
|
36
|
+
this.transactionGiveBySelect.forEach((giveBySelect) => {
|
|
37
|
+
if (isCard && giveBySelect.value.toLowerCase() === "card") {
|
|
38
|
+
giveBySelect.checked = true;
|
|
39
|
+
}
|
|
40
|
+
else if (giveBySelect.value.toLowerCase() === paymentType.toLowerCase()) {
|
|
41
|
+
giveBySelect.checked = true;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Returns true if the selected payment type is visible
|
|
47
|
+
// Returns false if the selected payment type is not visible
|
|
48
|
+
isSelectedPaymentVisible() {
|
|
49
|
+
let visible = true;
|
|
50
|
+
this.transactionGiveBySelect.forEach((giveBySelect) => {
|
|
51
|
+
const container = giveBySelect.parentElement;
|
|
52
|
+
if (giveBySelect.checked && !ENGrid.isVisible(container)) {
|
|
53
|
+
this.logger.log(`Selected Payment Type is not visible: ${giveBySelect.value}`);
|
|
54
|
+
visible = false;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return visible;
|
|
58
|
+
}
|
|
59
|
+
// Checks if the selected payment type is visible
|
|
60
|
+
// If the selected payment type is not visible, it sets the payment type to the first visible option
|
|
61
|
+
checkPaymentTypeVisibility() {
|
|
62
|
+
window.setTimeout(() => {
|
|
63
|
+
var _a;
|
|
64
|
+
if (!this.isSelectedPaymentVisible()) {
|
|
65
|
+
this.logger.log("Setting payment type to first visible option");
|
|
66
|
+
const firstVisible = Array.from(this.transactionGiveBySelect).find((giveBySelect) => {
|
|
67
|
+
const container = giveBySelect.parentElement;
|
|
68
|
+
return ENGrid.isVisible(container);
|
|
69
|
+
});
|
|
70
|
+
if (firstVisible) {
|
|
71
|
+
this.logger.log("Setting payment type to ", firstVisible.value);
|
|
72
|
+
const container = firstVisible.parentElement;
|
|
73
|
+
(_a = container.querySelector("label")) === null || _a === void 0 ? void 0 : _a.click();
|
|
74
|
+
ENGrid.setPaymentType(firstVisible.value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.logger.log("Selected Payment Type is visible");
|
|
79
|
+
}
|
|
80
|
+
}, 300);
|
|
81
|
+
}
|
|
82
|
+
}
|
package/dist/iframe.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EnForm } from "./events";
|
|
2
|
+
export declare class iFrame {
|
|
3
|
+
_form: EnForm;
|
|
4
|
+
private logger;
|
|
5
|
+
constructor();
|
|
6
|
+
private sendIframeHeight;
|
|
7
|
+
private sendIframeFormStatus;
|
|
8
|
+
private getIFrameByEvent;
|
|
9
|
+
private shouldScroll;
|
|
10
|
+
private inIframe;
|
|
11
|
+
private isChained;
|
|
12
|
+
private hideFormComponents;
|
|
13
|
+
private showFormComponents;
|
|
14
|
+
private addChainedBanner;
|
|
15
|
+
private debounceWithImmediate;
|
|
16
|
+
}
|