@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,161 @@
|
|
|
1
|
+
import { ENGrid, EngridLogger } from ".";
|
|
2
|
+
export class ShowHideRadioCheckboxes {
|
|
3
|
+
// Create default data attributes on all fields
|
|
4
|
+
createDataAttributes() {
|
|
5
|
+
this.elements.forEach((item) => {
|
|
6
|
+
if (item instanceof HTMLInputElement) {
|
|
7
|
+
let inputValue = item.value.replace(/\W/g, "");
|
|
8
|
+
document
|
|
9
|
+
.querySelectorAll("." + this.classes + inputValue)
|
|
10
|
+
.forEach((el) => {
|
|
11
|
+
// Consider toggling "hide" class so these fields can be displayed when in a debug state
|
|
12
|
+
if (el instanceof HTMLElement) {
|
|
13
|
+
const fields = el.querySelectorAll("input[type='text'], input[type='number'], input[type='email'], select, textarea");
|
|
14
|
+
if (fields.length > 0) {
|
|
15
|
+
fields.forEach((field) => {
|
|
16
|
+
if (field instanceof HTMLInputElement ||
|
|
17
|
+
field instanceof HTMLSelectElement) {
|
|
18
|
+
if (!field.hasAttribute("data-original-value")) {
|
|
19
|
+
field.setAttribute("data-original-value", field.value);
|
|
20
|
+
}
|
|
21
|
+
if (!field.hasAttribute("data-value")) {
|
|
22
|
+
field.setAttribute("data-value", field.value);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
// Hide All Divs
|
|
33
|
+
hideAll() {
|
|
34
|
+
this.elements.forEach((item, index) => {
|
|
35
|
+
if (item instanceof HTMLInputElement)
|
|
36
|
+
this.hide(item);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
// Hide Single Element Div
|
|
40
|
+
hide(item) {
|
|
41
|
+
let inputValue = item.value.replace(/\W/g, "");
|
|
42
|
+
document.querySelectorAll("." + this.classes + inputValue).forEach((el) => {
|
|
43
|
+
// Consider toggling "hide" class so these fields can be displayed when in a debug state
|
|
44
|
+
if (el instanceof HTMLElement) {
|
|
45
|
+
this.toggleValue(el, "hide");
|
|
46
|
+
el.style.display = "none";
|
|
47
|
+
this.logger.log("Hiding", el);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
// Show Single Element Div
|
|
52
|
+
show(item) {
|
|
53
|
+
let inputValue = item.value.replace(/\W/g, "");
|
|
54
|
+
document.querySelectorAll("." + this.classes + inputValue).forEach((el) => {
|
|
55
|
+
// Consider toggling "hide" class so these fields can be displayed when in a debug state
|
|
56
|
+
if (el instanceof HTMLElement) {
|
|
57
|
+
this.toggleValue(el, "show");
|
|
58
|
+
el.style.display = "";
|
|
59
|
+
this.logger.log("Showing", el);
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
if (item.type == "checkbox" && !item.checked) {
|
|
63
|
+
this.hide(item);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Take the field values and add to a data attribute on the field
|
|
67
|
+
toggleValue(item, type) {
|
|
68
|
+
if (type == "hide" && !ENGrid.isVisible(item))
|
|
69
|
+
return;
|
|
70
|
+
this.logger.log(`toggleValue: ${type}`);
|
|
71
|
+
const fields = item.querySelectorAll("input[type='text'], input[type='number'], input[type='email'], select, textarea");
|
|
72
|
+
if (fields.length > 0) {
|
|
73
|
+
fields.forEach((field) => {
|
|
74
|
+
var _a;
|
|
75
|
+
if (field instanceof HTMLInputElement ||
|
|
76
|
+
field instanceof HTMLSelectElement) {
|
|
77
|
+
if (field.name) {
|
|
78
|
+
const fieldValue = ENGrid.getFieldValue(field.name);
|
|
79
|
+
const originalValue = field.getAttribute("data-original-value");
|
|
80
|
+
const dataValue = (_a = field.getAttribute("data-value")) !== null && _a !== void 0 ? _a : "";
|
|
81
|
+
if (type === "hide") {
|
|
82
|
+
field.setAttribute("data-value", fieldValue);
|
|
83
|
+
ENGrid.setFieldValue(field.name, originalValue);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
ENGrid.setFieldValue(field.name, dataValue);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
getSessionState() {
|
|
94
|
+
var _a;
|
|
95
|
+
try {
|
|
96
|
+
const plainState = (_a = window.sessionStorage.getItem(`engrid_ShowHideRadioCheckboxesState`)) !== null && _a !== void 0 ? _a : "";
|
|
97
|
+
return JSON.parse(plainState);
|
|
98
|
+
}
|
|
99
|
+
catch (err) {
|
|
100
|
+
return [];
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
storeSessionState() {
|
|
104
|
+
const state = this.getSessionState();
|
|
105
|
+
[...this.elements].forEach((element) => {
|
|
106
|
+
var _a, _b;
|
|
107
|
+
if (!(element instanceof HTMLInputElement))
|
|
108
|
+
return;
|
|
109
|
+
if (element.type == "radio" && element.checked) {
|
|
110
|
+
//remove other items that have the same "class" property
|
|
111
|
+
state.forEach((item, index) => {
|
|
112
|
+
if (item.class == this.classes) {
|
|
113
|
+
state.splice(index, 1);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
//add the current item, with the currently active value
|
|
117
|
+
state.push({
|
|
118
|
+
page: ENGrid.getPageID(),
|
|
119
|
+
class: this.classes,
|
|
120
|
+
value: element.value,
|
|
121
|
+
});
|
|
122
|
+
this.logger.log("storing radio state", state[state.length - 1]);
|
|
123
|
+
}
|
|
124
|
+
if (element.type == "checkbox") {
|
|
125
|
+
//remove other items that have the same "class" property
|
|
126
|
+
state.forEach((item, index) => {
|
|
127
|
+
if (item.class == this.classes) {
|
|
128
|
+
state.splice(index, 1);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
//add the current item, with the first checked value or "N" if none are checked
|
|
132
|
+
state.push({
|
|
133
|
+
page: ENGrid.getPageID(),
|
|
134
|
+
class: this.classes,
|
|
135
|
+
value: (_b = (_a = [...this.elements].find((el) => el.checked)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : "N", // First checked value or "N" if none
|
|
136
|
+
});
|
|
137
|
+
this.logger.log("storing checkbox state", state[state.length - 1]);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
window.sessionStorage.setItem(`engrid_ShowHideRadioCheckboxesState`, JSON.stringify(state));
|
|
141
|
+
}
|
|
142
|
+
constructor(elements, classes) {
|
|
143
|
+
this.logger = new EngridLogger("ShowHideRadioCheckboxes", "black", "lightblue", "👁");
|
|
144
|
+
this.elements = document.getElementsByName(elements);
|
|
145
|
+
this.classes = classes;
|
|
146
|
+
this.createDataAttributes();
|
|
147
|
+
this.hideAll();
|
|
148
|
+
this.storeSessionState();
|
|
149
|
+
for (let i = 0; i < this.elements.length; i++) {
|
|
150
|
+
let element = this.elements[i];
|
|
151
|
+
if (element.checked) {
|
|
152
|
+
this.show(element);
|
|
153
|
+
}
|
|
154
|
+
element.addEventListener("change", (e) => {
|
|
155
|
+
this.hideAll();
|
|
156
|
+
this.show(element);
|
|
157
|
+
this.storeSessionState();
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { DonationAmount } from "./events";
|
|
2
|
+
export declare class ShowIfAmount {
|
|
3
|
+
_amount: DonationAmount;
|
|
4
|
+
private _elements;
|
|
5
|
+
private logger;
|
|
6
|
+
constructor();
|
|
7
|
+
private init;
|
|
8
|
+
private getClassNameByOperand;
|
|
9
|
+
private lessthan;
|
|
10
|
+
private lessthanorequalto;
|
|
11
|
+
private equalto;
|
|
12
|
+
private greaterthanorequalto;
|
|
13
|
+
private greaterthan;
|
|
14
|
+
private between;
|
|
15
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { ENGrid, EngridLogger } from ".";
|
|
2
|
+
import { DonationAmount } from "./events";
|
|
3
|
+
export class ShowIfAmount {
|
|
4
|
+
constructor() {
|
|
5
|
+
this._amount = DonationAmount.getInstance();
|
|
6
|
+
this.logger = new EngridLogger("ShowIfAmount", "yellow", "black", "👀");
|
|
7
|
+
this._elements = document.querySelectorAll('[class*="showifamount"]');
|
|
8
|
+
if (this._elements.length > 0) {
|
|
9
|
+
this._amount.onAmountChange.subscribe(() => this.init());
|
|
10
|
+
this.init();
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
this.logger.log("Show If Amount: NO ELEMENTS FOUND");
|
|
14
|
+
}
|
|
15
|
+
init() {
|
|
16
|
+
//If we are on a thank you page, use the window.pageJson.amount
|
|
17
|
+
const amount = ENGrid.getGiftProcess()
|
|
18
|
+
? window.pageJson.amount
|
|
19
|
+
: this._amount.amount;
|
|
20
|
+
this._elements.forEach((element) => {
|
|
21
|
+
this.lessthan(amount, element);
|
|
22
|
+
this.lessthanorequalto(amount, element);
|
|
23
|
+
this.equalto(amount, element);
|
|
24
|
+
this.greaterthanorequalto(amount, element);
|
|
25
|
+
this.greaterthan(amount, element);
|
|
26
|
+
this.between(amount, element);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
getClassNameByOperand(classList, operand) {
|
|
30
|
+
let myClass = null;
|
|
31
|
+
classList.forEach((className) => {
|
|
32
|
+
if (className.includes(`showifamount-${operand}-`)) {
|
|
33
|
+
myClass = className;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return myClass;
|
|
37
|
+
}
|
|
38
|
+
lessthan(amount, element) {
|
|
39
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "lessthan");
|
|
40
|
+
if (showifamountClass) {
|
|
41
|
+
let amountCheck = showifamountClass.split("-").slice(-1)[0];
|
|
42
|
+
if (amount < Number(amountCheck)) {
|
|
43
|
+
this.logger.log("(lessthan):", element);
|
|
44
|
+
element.classList.add("engrid-open");
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
element.classList.remove("engrid-open");
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
lessthanorequalto(amount, element) {
|
|
52
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "lessthanorequalto");
|
|
53
|
+
if (showifamountClass) {
|
|
54
|
+
let amountCheck = showifamountClass.split("-").slice(-1)[0];
|
|
55
|
+
if (amount <= Number(amountCheck)) {
|
|
56
|
+
this.logger.log("(lessthanorequalto):", element);
|
|
57
|
+
element.classList.add("engrid-open");
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
element.classList.remove("engrid-open");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
equalto(amount, element) {
|
|
65
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "equalto");
|
|
66
|
+
if (showifamountClass) {
|
|
67
|
+
let amountCheck = showifamountClass.split("-").slice(-1)[0];
|
|
68
|
+
if (amount == Number(amountCheck)) {
|
|
69
|
+
this.logger.log("(equalto):", element);
|
|
70
|
+
element.classList.add("engrid-open");
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
element.classList.remove("engrid-open");
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
greaterthanorequalto(amount, element) {
|
|
78
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "greaterthanorequalto");
|
|
79
|
+
if (showifamountClass) {
|
|
80
|
+
let amountCheck = showifamountClass.split("-").slice(-1)[0];
|
|
81
|
+
if (amount >= Number(amountCheck)) {
|
|
82
|
+
this.logger.log("(greaterthanorequalto):", element);
|
|
83
|
+
element.classList.add("engrid-open");
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
element.classList.remove("engrid-open");
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
greaterthan(amount, element) {
|
|
91
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "greaterthan");
|
|
92
|
+
if (showifamountClass) {
|
|
93
|
+
let amountCheck = showifamountClass.split("-").slice(-1)[0];
|
|
94
|
+
if (amount > Number(amountCheck)) {
|
|
95
|
+
this.logger.log("(greaterthan):", element);
|
|
96
|
+
element.classList.add("engrid-open");
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
element.classList.remove("engrid-open");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
between(amount, element) {
|
|
104
|
+
const showifamountClass = this.getClassNameByOperand(element.classList, "between");
|
|
105
|
+
if (showifamountClass) {
|
|
106
|
+
let amountCheckMin = showifamountClass.split("-").slice(-2, -1)[0];
|
|
107
|
+
let amountCheckMax = showifamountClass.split("-").slice(-1)[0];
|
|
108
|
+
if (amount > Number(amountCheckMin) && amount < Number(amountCheckMax)) {
|
|
109
|
+
this.logger.log("(between):", element);
|
|
110
|
+
element.classList.add("engrid-open");
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
element.classList.remove("engrid-open");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This class contains the logic for special classes that can be used to hide elements if
|
|
3
|
+
* certain supporter questions are present or absent.
|
|
4
|
+
* Typically, this can be used to hide elements when an opt in question is not rendered on the page
|
|
5
|
+
* because the supporter came from a campaign link and is already opted in, so EN doesn't render
|
|
6
|
+
* the question on the page.
|
|
7
|
+
*
|
|
8
|
+
* The class names are of the format:
|
|
9
|
+
* engrid__supporterquestions{id}-present -- show this element when the supporter question is present
|
|
10
|
+
* engrid__supporterquestions{id}-absent -- show this element when the supporter question is absent
|
|
11
|
+
*
|
|
12
|
+
* The {id} is the id of the supporter question. This can be found by inspecting the element on the page.
|
|
13
|
+
*
|
|
14
|
+
* It's also possible to combine multiple questions using the following format. These examples show 2 questions,
|
|
15
|
+
* but you can use as many as you like:
|
|
16
|
+
* engrid__supporterquestions{id1}__supporterquestions{id2}-present -- show this element when EITHER question is present
|
|
17
|
+
* engrid__supporterquestions{id1}__supporterquestions{id2}-absent -- show this element when EITHER question is absent
|
|
18
|
+
*/
|
|
19
|
+
import { EngridLogger } from "./logger";
|
|
20
|
+
export class ShowIfPresent {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.logger = new EngridLogger("ShowIfPresent", "yellow", "black", "👀");
|
|
23
|
+
this.elements = [];
|
|
24
|
+
if (this.shouldRun()) {
|
|
25
|
+
this.run();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
shouldRun() {
|
|
29
|
+
// Check if we have any elements on the page that match the pattern for this functionality
|
|
30
|
+
// e.g. engrid__supporterquestions{id}__supporterquestions{id}-present, etc.
|
|
31
|
+
this.elements = [
|
|
32
|
+
...document.querySelectorAll('[class*="engrid__supporterquestions"]'),
|
|
33
|
+
].filter((el) => {
|
|
34
|
+
const classNames = el.className.split(" ");
|
|
35
|
+
return classNames.some((className) => /^engrid__supporterquestions\d+(__supporterquestions\d+)*-(present|absent)$/.test(className));
|
|
36
|
+
});
|
|
37
|
+
return this.elements.length > 0;
|
|
38
|
+
}
|
|
39
|
+
run() {
|
|
40
|
+
const actions = [];
|
|
41
|
+
// Create an array of actions for each element we have
|
|
42
|
+
this.elements.forEach((el) => {
|
|
43
|
+
// Mapping to an object with the class name, field name(s), and type
|
|
44
|
+
const classNames = el.className.split(" ");
|
|
45
|
+
const matchingClass = classNames.find((className) => /^engrid__supporterquestions\d+(__supporterquestions\d+)*-(present|absent)$/.test(className));
|
|
46
|
+
if (!matchingClass)
|
|
47
|
+
return null;
|
|
48
|
+
const typeIndex = matchingClass.lastIndexOf("-");
|
|
49
|
+
const type = matchingClass.substring(typeIndex + 1);
|
|
50
|
+
// Getting an array of the matching input names
|
|
51
|
+
// e.g. engrid__supporterquestions12345-present => ['supporter.questions.12345']
|
|
52
|
+
// e.g. engrid__supporterquestions12345__supporterquestions67890-present => ['supporter.questions.12345', 'supporter.questions.67890']
|
|
53
|
+
const inputIds = matchingClass
|
|
54
|
+
.substring(8, typeIndex)
|
|
55
|
+
.split("__")
|
|
56
|
+
.map((id) => `supporter.questions.${id.substring(18)}`);
|
|
57
|
+
actions.push({
|
|
58
|
+
class: matchingClass,
|
|
59
|
+
fieldNames: inputIds,
|
|
60
|
+
type: type,
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
//Process the actions
|
|
64
|
+
actions.forEach((action) => {
|
|
65
|
+
const inputElements = action.fieldNames.map((fieldName) => document.getElementsByName(fieldName)[0]);
|
|
66
|
+
const elements = document.querySelectorAll(`.${action.class}`);
|
|
67
|
+
const areAllInputsPresent = inputElements.every((input) => !!input);
|
|
68
|
+
const areAllInputsAbsent = inputElements.every((input) => !input);
|
|
69
|
+
// Hide the elements based on AND conditions
|
|
70
|
+
if ((action.type === "present" && areAllInputsAbsent) ||
|
|
71
|
+
(action.type === "absent" && areAllInputsPresent)) {
|
|
72
|
+
this.logger.log(`Conditions not met, hiding elements with class ${action.class}`);
|
|
73
|
+
elements.forEach((el) => {
|
|
74
|
+
el.style.display = "none";
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Javascript that adds an accessible "Skip Link" button after the <body> opening that jumps to
|
|
2
|
+
// the first <title> or <h1> field in a "body-" section, or the first <h1> if none are found
|
|
3
|
+
// in those sections
|
|
4
|
+
// Depends on _engrid-skip-link.scss
|
|
5
|
+
import { ENGrid } from ".";
|
|
6
|
+
export class SkipToMainContentLink {
|
|
7
|
+
constructor() {
|
|
8
|
+
const firstTitleInEngridBody = document.querySelector("div[class*='body-'] title");
|
|
9
|
+
const firstH1InEngridBody = document.querySelector("div[class*='body-'] h1");
|
|
10
|
+
const firstTitle = document.querySelector("title");
|
|
11
|
+
const firstH1 = document.querySelector("h1");
|
|
12
|
+
if (firstTitleInEngridBody && firstTitleInEngridBody.parentElement) {
|
|
13
|
+
firstTitleInEngridBody.parentElement.insertAdjacentHTML("beforebegin", '<span id="skip-link"></span>');
|
|
14
|
+
this.insertSkipLinkSpan();
|
|
15
|
+
}
|
|
16
|
+
else if (firstH1InEngridBody && firstH1InEngridBody.parentElement) {
|
|
17
|
+
firstH1InEngridBody.parentElement.insertAdjacentHTML("beforebegin", '<span id="skip-link"></span>');
|
|
18
|
+
this.insertSkipLinkSpan();
|
|
19
|
+
}
|
|
20
|
+
else if (firstTitle && firstTitle.parentElement) {
|
|
21
|
+
firstTitle.parentElement.insertAdjacentHTML("beforebegin", '<span id="skip-link"></span>');
|
|
22
|
+
this.insertSkipLinkSpan();
|
|
23
|
+
}
|
|
24
|
+
else if (firstH1 && firstH1.parentElement) {
|
|
25
|
+
firstH1.parentElement.insertAdjacentHTML("beforebegin", '<span id="skip-link"></span>');
|
|
26
|
+
this.insertSkipLinkSpan();
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
if (ENGrid.debug)
|
|
30
|
+
console.log("This page contains no <title> or <h1> and a 'Skip to main content' link was not added");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
insertSkipLinkSpan() {
|
|
34
|
+
document.body.insertAdjacentHTML("afterbegin", '<a class="skip-link" href="#skip-link">Skip to main content</a>');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Build Notes: Add the vanilla Javascript version inline inside the page template right before </body>
|
|
2
|
+
// In the event the vanilla javascript is not inlined we should still process any assets with a data-src still defined on it. Plus we only process background video via this JS file as to not block the page with a large video file downloading.
|
|
3
|
+
// // 4Site's simplified image lazy loader
|
|
4
|
+
// var srcDefer = document.querySelectorAll("img[data-src]");
|
|
5
|
+
// window.addEventListener('DOMContentLoaded', (event) => {
|
|
6
|
+
// for (var i = 0; i < srcDefer.length; i++) {
|
|
7
|
+
// let dataSrc = srcDefer[i].getAttribute("data-src");
|
|
8
|
+
// if (dataSrc) {
|
|
9
|
+
// srcDefer[i].setAttribute("decoding", "async"); // Gets image processing off the main working thread
|
|
10
|
+
// srcDefer[i].setAttribute("loading", "lazy"); // Lets the browser determine when the asset should be downloaded
|
|
11
|
+
// srcDefer[i].setAttribute("src", dataSrc); // Sets the src which will cause the browser to retrieve the asset
|
|
12
|
+
// srcDefer[i].setAttribute("data-engrid-data-src-processed", "true"); // Sets an attribute to mark that it has been processed by ENGrid
|
|
13
|
+
// srcDefer[i].removeAttribute("data-src"); // Removes the data-source
|
|
14
|
+
// }
|
|
15
|
+
// }
|
|
16
|
+
// });
|
|
17
|
+
export class SrcDefer {
|
|
18
|
+
constructor() {
|
|
19
|
+
// Find all images and videos with a data-src defined
|
|
20
|
+
this.imgSrcDefer = document.querySelectorAll("img[data-src]");
|
|
21
|
+
this.videoBackground = document.querySelectorAll("video");
|
|
22
|
+
this.videoBackgroundSource = document.querySelectorAll("video source");
|
|
23
|
+
// Process images
|
|
24
|
+
for (let i = 0; i < this.imgSrcDefer.length; i++) {
|
|
25
|
+
let img = this.imgSrcDefer[i];
|
|
26
|
+
if (img) {
|
|
27
|
+
img.setAttribute("decoding", "async"); // Gets image processing off the main working thread, and decodes the image asynchronously to reduce delay in presenting other content
|
|
28
|
+
img.setAttribute("loading", "lazy"); // Lets the browser determine when the asset should be downloaded using it's native lazy loading
|
|
29
|
+
let imgDataSrc = img.getAttribute("data-src");
|
|
30
|
+
if (imgDataSrc) {
|
|
31
|
+
img.setAttribute("src", imgDataSrc); // Sets the src which will cause the browser to retrieve the asset
|
|
32
|
+
}
|
|
33
|
+
img.setAttribute("data-engrid-data-src-processed", "true"); // Sets an attribute to mark that it has been processed by ENGrid
|
|
34
|
+
img.removeAttribute("data-src"); // Removes the data-source
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Process video
|
|
38
|
+
for (let i = 0; i < this.videoBackground.length; i++) {
|
|
39
|
+
let video = this.videoBackground[i];
|
|
40
|
+
// Process one or more defined sources in the <video> tag
|
|
41
|
+
this.videoBackgroundSource = video.querySelectorAll("source");
|
|
42
|
+
if (this.videoBackgroundSource) {
|
|
43
|
+
// loop through all the sources
|
|
44
|
+
for (let j = 0; j < this.videoBackgroundSource.length; j++) {
|
|
45
|
+
let videoSource = this.videoBackgroundSource[j];
|
|
46
|
+
if (videoSource) {
|
|
47
|
+
let videoBackgroundSourcedDataSrc = videoSource.getAttribute("data-src");
|
|
48
|
+
if (videoBackgroundSourcedDataSrc) {
|
|
49
|
+
videoSource.setAttribute("src", videoBackgroundSourcedDataSrc);
|
|
50
|
+
videoSource.setAttribute("data-engrid-data-src-processed", "true"); // Sets an attribute to mark that it has been processed by ENGrid
|
|
51
|
+
videoSource.removeAttribute("data-src"); // Removes the data-source
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// To get the browser to request the video asset defined we need to remove the <video> tag and re-add it
|
|
56
|
+
let videoBackgroundParent = video.parentNode; // Determine the parent of the <video> tag
|
|
57
|
+
let copyOfVideoBackground = video; // Copy the <video> tag
|
|
58
|
+
if (videoBackgroundParent && copyOfVideoBackground) {
|
|
59
|
+
videoBackgroundParent.replaceChild(copyOfVideoBackground, video); // Replace the <video> with the copy of itself
|
|
60
|
+
// Update the video to auto play, mute, loop
|
|
61
|
+
video.muted = true; // Mute the video by default
|
|
62
|
+
video.controls = false; // Hide the browser controls
|
|
63
|
+
video.loop = true; // Loop the video
|
|
64
|
+
video.playsInline = true; // Encourage the user agent to display video content within the element's playback area
|
|
65
|
+
video.play(); // Plays the video
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Component that adds 4Site Special Features to the Supporter Hub Page
|
|
2
|
+
import { ENGrid, EngridLogger, EnForm } from ".";
|
|
3
|
+
export class SupporterHub {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.logger = new EngridLogger("SupporterHub", "black", "pink", "🛖");
|
|
6
|
+
this._form = EnForm.getInstance();
|
|
7
|
+
if (!this.shoudRun())
|
|
8
|
+
return;
|
|
9
|
+
this.logger.log("Enabled");
|
|
10
|
+
this.watch();
|
|
11
|
+
}
|
|
12
|
+
shoudRun() {
|
|
13
|
+
return ("pageJson" in window &&
|
|
14
|
+
"pageType" in window.pageJson &&
|
|
15
|
+
window.pageJson.pageType === "supporterhub");
|
|
16
|
+
}
|
|
17
|
+
watch() {
|
|
18
|
+
const form = ENGrid.enForm;
|
|
19
|
+
// Create a observer to watch the Form for overlays
|
|
20
|
+
const observer = new MutationObserver((mutations) => {
|
|
21
|
+
mutations.forEach((mutation) => {
|
|
22
|
+
if (mutation.type === "childList") {
|
|
23
|
+
mutation.addedNodes.forEach((node) => {
|
|
24
|
+
if (node.nodeName === "DIV") {
|
|
25
|
+
const overlay = node;
|
|
26
|
+
if (overlay.classList.contains("en__hubOverlay") ||
|
|
27
|
+
overlay.classList.contains("en__hubPledge__panels")) {
|
|
28
|
+
this.logger.log("Overlay found");
|
|
29
|
+
this.creditCardUpdate(node);
|
|
30
|
+
this.amountLabelUpdate(node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
// Start observing the Link ID #plaid-link-button
|
|
38
|
+
observer.observe(form, {
|
|
39
|
+
childList: true,
|
|
40
|
+
subtree: true,
|
|
41
|
+
});
|
|
42
|
+
// Run the Credit Card Update function in case the overlay is already present on page load
|
|
43
|
+
const hubOverlay = document.querySelector(".en__hubOverlay");
|
|
44
|
+
if (hubOverlay) {
|
|
45
|
+
this.creditCardUpdate(hubOverlay);
|
|
46
|
+
this.amountLabelUpdate(hubOverlay);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
creditCardUpdate(overlay) {
|
|
50
|
+
window.setTimeout(() => {
|
|
51
|
+
// Check if the overlay has Credit Card field and Update Button
|
|
52
|
+
const ccField = overlay.querySelector("#en__hubPledge__field--ccnumber"), updateButton = overlay.querySelector(".en__hubUpdateCC__toggle");
|
|
53
|
+
if (ccField && updateButton) {
|
|
54
|
+
// When field gets focus, click the update button
|
|
55
|
+
ccField.addEventListener("focus", () => {
|
|
56
|
+
this.logger.log("Credit Card field focused");
|
|
57
|
+
updateButton.click();
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}, 300);
|
|
61
|
+
}
|
|
62
|
+
amountLabelUpdate(overlay) {
|
|
63
|
+
window.setTimeout(() => {
|
|
64
|
+
// Check if the overlay has Amounts, and set the currency symbol updated attribute
|
|
65
|
+
const amountContainer = overlay.querySelector(".en__field--donationAmt");
|
|
66
|
+
if (amountContainer) {
|
|
67
|
+
amountContainer
|
|
68
|
+
.querySelectorAll(".en__field__element--radio .en__field__item")
|
|
69
|
+
.forEach((node) => {
|
|
70
|
+
node.setAttribute("data-engrid-currency-symbol-updated", "true");
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}, 300);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example:
|
|
3
|
+
* window.EngridAmounts = {
|
|
4
|
+
* "onetime": {
|
|
5
|
+
* amounts: {
|
|
6
|
+
* "10": 10,
|
|
7
|
+
* "30": 30,
|
|
8
|
+
* "50": 50,
|
|
9
|
+
* "100": 100,
|
|
10
|
+
* "Other": "other",
|
|
11
|
+
* },
|
|
12
|
+
* default: 30,
|
|
13
|
+
* },
|
|
14
|
+
* "monthly": {
|
|
15
|
+
* amounts: {
|
|
16
|
+
* "5": 5,
|
|
17
|
+
* "15": 15,
|
|
18
|
+
* "25": 25,
|
|
19
|
+
* "30": 30,
|
|
20
|
+
* "Other": "other",
|
|
21
|
+
* },
|
|
22
|
+
* default: 15,
|
|
23
|
+
* },
|
|
24
|
+
* };
|
|
25
|
+
*/
|
|
26
|
+
import { DonationAmount } from ".";
|
|
27
|
+
export declare class SwapAmounts {
|
|
28
|
+
private logger;
|
|
29
|
+
_amount: DonationAmount;
|
|
30
|
+
private _frequency;
|
|
31
|
+
private defaultChange;
|
|
32
|
+
private swapped;
|
|
33
|
+
constructor();
|
|
34
|
+
swapAmounts(): void;
|
|
35
|
+
loadEnAmounts(amountArray: {
|
|
36
|
+
amounts: [string, number];
|
|
37
|
+
default: number;
|
|
38
|
+
}): {
|
|
39
|
+
selected: boolean;
|
|
40
|
+
label: string;
|
|
41
|
+
value: string;
|
|
42
|
+
}[];
|
|
43
|
+
shouldRun(): boolean;
|
|
44
|
+
ignoreCurrentValue(): boolean;
|
|
45
|
+
}
|