");vwo_$('head').append(_vwo_sel);return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("HEAD")}}, R_940895_48_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var ctx=vwo_$(x),el;
/*vwo_debug log("Revert","content",""); vwo_debug*/;
el=vwo_$('[vwo-element-id="1742919897117"]');
el.revertContentOp().remove();})("HEAD")}}, C_940895_48_1_2_1:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement",".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)")).html("Hello! David Brancaccio here. Do you want instant access to the free online course - “Economics 101” - to understand basic economic concepts?");})(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)")}}, R_940895_48_1_2_1:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement",".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)")).vwoRevertHtml();})(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > h2:nth-of-type(1) > span:nth-of-type(1)")}}, C_940895_48_1_2_2:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("content","[vwo-element-id='1742482566780']"); vwo_debug*/(el=vwo_$("[vwo-element-id='1742482566780']")).replaceWith2("You'll gain real-world insights into how economics impacts your daily life with this easy-to-follow online course. This crash course is based on the acclaimed textbook Economy, Society, and Public Policy by CORE Econ, tailored to help you grasp key concepts without feeling overwhelmed.
Whether you're new to economics or just want to deepen your understanding, this course covers the basics and connects them to today’s pressing issues—from inequality to public policy decisions.
Each week, you'll receive a reading guide that distills core principles, offers actionable takeaways, and explains how they affect the current world. While the full ebook enriches the experience, the guides alone provide a comprehensive understanding of fundamental economic ideas.
You’ll find this course especially useful and unique because…"),el=vwo_$("[vwo-element-id='1742482566780']");})("[vwo-element-id='1742482566780']")}}, R_940895_48_1_2_2:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","content","[vwo-element-id='1742482566780']"); vwo_debug*/(el=vwo_$("[vwo-element-id='1742482566780']")).revertContentOp(),el=vwo_$("[vwo-element-id='1742482566780']");})("[vwo-element-id='1742482566780']")}}, C_940895_62_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("visibility","H1:tm('Support The Splendid Table Today')"); vwo_debug*/(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoCss({visibility:"hidden !important"}),(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoCss({display:"none !important"});})("H1:tm('Support The Splendid Table Today')")}}, R_940895_62_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","H1:tm('Support The Splendid Table Today')"); vwo_debug*/(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoRevertCss(),(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoRevertCss();})("H1:tm('Support The Splendid Table Today')")}}, C_940895_62_1_2_1:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","STRONG:tm('Success! You’re subscribed!')"); vwo_debug*/(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoCss({"font-size":"22px !important"}),(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoCss({"font-size":"24px !important"});})("STRONG:tm('Success! You’re subscribed!')")}}, R_940895_62_1_2_1:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","STRONG:tm('Success! You’re subscribed!')"); vwo_debug*/(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoRevertCss(),(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoRevertCss();})("STRONG:tm('Success! You’re subscribed!')")}}, C_940895_62_1_3_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("visibility","H1:tm('Support The Splendid Table Today')"); vwo_debug*/(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoCss({visibility:"hidden !important"}),(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoCss({display:"none !important"});})("H1:tm('Support The Splendid Table Today')")}}, R_940895_62_1_3_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","H1:tm('Support The Splendid Table Today')"); vwo_debug*/(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoRevertCss(),(el=vwo_$("H1:tm('Support The Splendid Table Today')")).vwoRevertCss();})("H1:tm('Support The Splendid Table Today')")}}, C_940895_62_1_3_1:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","STRONG:tm('Success! You’re subscribed!')"); vwo_debug*/(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoCss({"font-size":"22px !important"}),(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoCss({"font-size":"24px !important"}),(el=vwo_$(".vwo_tm_1742501918554 STRONG:tm('Success! You’re subscribed!')")).html("You are now subscribed to the Weeknight Kitchen newsletter! Before you go, would you consider something?"),el.addClass("vwo_tm_1742501918554");})(".vwo_tm_1742501918554 STRONG:tm('Success! You’re subscribed!')")}}, R_940895_62_1_3_1:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","STRONG:tm('Success! You’re subscribed!')"); vwo_debug*/(el=vwo_$(".vwo_tm_1742501918554 STRONG:tm('Success! You’re subscribed!')")).vwoRevertHtml(),(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoRevertCss(),(el=vwo_$("STRONG:tm('Success! You’re subscribed!')")).vwoRevertCss();})(".vwo_tm_1742501918554 STRONG:tm('Success! You’re subscribed!')")}}, C_940895_62_1_3_2:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("remove",".field-item > p:nth-of-type(2)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(2)")).vwoCss({display:"none !important"});})(".field-item > p:nth-of-type(2)")}}, R_940895_62_1_3_2:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove",".field-item > p:nth-of-type(2)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(2)")).vwoRevertCss();})(".field-item > p:nth-of-type(2)")}}, C_940895_62_1_3_3:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("remove","STRONG:tm('Before you go, would you consider something?')"); vwo_debug*/(el=vwo_$("STRONG:tm('Before you go, would you consider something?')")).vwoCss({display:"none !important"});})("STRONG:tm('Before you go, would you consider something?')")}}, R_940895_62_1_3_3:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","STRONG:tm('Before you go, would you consider something?')"); vwo_debug*/(el=vwo_$("STRONG:tm('Before you go, would you consider something?')")).vwoRevertCss();})("STRONG:tm('Before you go, would you consider something?')")}}, C_940895_59_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("remove visibility",".field-item > p:nth-of-type(2)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(2)")).vwoCss({visibility:"hidden !important",display:"none !important"});})(".field-item > p:nth-of-type(2)")}}, R_940895_59_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove visibility",".field-item > p:nth-of-type(2)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(2)")).vwoRevertCss();})(".field-item > p:nth-of-type(2)")}}, C_940895_59_1_2_1:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement",".field-item > p:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(1)")).html("When you become a Marketplace Investor today, you’re more than just a listener: you’re a vital partner in our mission to make people smarter about the economy, tech, and the world, every day. Your donation today makes for a better Marketplace tomorrow.");})(".field-item > p:nth-of-type(1)")}}, R_940895_59_1_2_1:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement",".field-item > p:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".field-item > p:nth-of-type(1)")).vwoRevertHtml();})(".field-item > p:nth-of-type(1)")}}, C_940895_55_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("remove","H1:tm('Support MPR News Today!')"); vwo_debug*/(el=vwo_$("H1:tm('Support MPR News Today!')")).vwoCss({display:"none !important"});})("H1:tm('Support MPR News Today!')")}}, R_940895_55_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","H1:tm('Support MPR News Today!')"); vwo_debug*/(el=vwo_$("H1:tm('Support MPR News Today!')")).vwoRevertCss();})("H1:tm('Support MPR News Today!')")}}, C_940895_48_1_2_4:{ fn:function(log,nonce=''){return (function(x) {})(".author,.img-wrapper,.img-wrapper img,.author-copy")}}, R_940895_48_1_2_3:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","content",".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)")).revertContentOp(),el=vwo_$(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)");})(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)")}}, C_940895_48_1_2_3:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("content",".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)"); vwo_debug*/(el=vwo_$(".stylingblock-content-margin-cell > table:nth-of-type(1) > tbody:nth-of-type(1) > tr:nth-of-type(1) > td:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1) > div:nth-of-type(1)")).replaceWith2("
You'll gain real-world insights into how economics impacts your daily life with this easy-to-follow online course. This crash course is based on the acclaimed textbook Economy, Society, and Public Policy by CORE Econ, tailored to help you grasp key concepts without feeling overwhelmed.
Whether you're new to economics or just want to deepen your understanding, this course covers the basics and connects them to today’s pressing issues—from inequality to public policy decisions.
Each week, you'll receive a reading guide that distills core principles, offers actionable takeaways, and explains how they affect the current world. While the full ebook enriches the experience, the guides alone provide a comprehensive understanding of fundamental economic ideas.
You’ll find this course especially useful and unique because…
It allows you to understand economics in action: Real-life examples and analysis of current events that show you economics at work.
There’s no prior knowledge required: Complex ideas are broken into simple, relatable explanations.
You can be flexible with your learning according to your lifestyle: Go at your own pace, with weekly guides that fit your schedule.
Are you ready to build a foundation in economics that empowers you to think critically about the world around you?
Get instant access today and keep an eye on your inbox for a confirmation email and your first lesson.
By submitting, you consent to receive information about MPR\'s programs and offerings. You may opt-out at any time clicking the unsubscribe link at the bottom of any email communication. View our Privacy Policy.
'),(el=vwo_$("#tfa_31-HTML > p:nth-of-type(1)")).vwoCss({display:"none !important"});})(".hintsBelow")}}, R_940895_54_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","H1:tm('Support MPR News Today!')"); vwo_debug*/(el=vwo_$("H1:tm('Support MPR News Today!')")).vwoRevertCss();})("H1:tm('Support MPR News Today!')")}}, C_940895_39_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
try{
var _vwo_sel = vwo_$("`);
!vwo_$("head").find('#1740425171461').length && vwo_$('head').append(_vwo_sel);}catch(e) {console.error(e)}
try{}catch(e) {console.error(e)}
try{const getCurrentDate = (d = new Date()) => d.toISOString().split('T')[0];
function vwoCustomEvent (labelValue) {
window.VWO = window.VWO || [];
VWO.event = VWO.event || function () {VWO.push(["event"].concat([].slice.call(arguments)))};
VWO.event("customEvent", { "label": labelValue.toString() });
}
class RadioButtonComponent {
constructor (element) {
this.radio = element.querySelector('input[type="radio"]');
this.label = element.querySelector('label');
}
get value () {
let value = this.radio.value;
if (Number.isNaN(parseFloat(value)))
return value;
if (parseFloat(value) % 1 == 0)
return parseInt(value);
return parseFloat(value);
}
set value (newValue) {
this.radio.value = newValue;
}
get text () {
return this.label.textContent;
}
set text (newText) {
if (this.label.querySelector('.form-required')) {
const labelTextNode = [...this.label.childNodes].filter(({ nodeType }) => nodeType === Node.TEXT_NODE)[0];
labelTextNode.nodeValue = newText;
} else {
this.label.textContent = newText;
}
}
get checked () {
return this.radio.checked;
}
set checked (bool) {
this.click(),
bool === true && this.radio.checked === true;
}
click () {
this.label.click();
}
select () {
this.click();
}
addEventListener (eventType, callbackFunction) {
switch (eventType) {
case 'click':
this.label.addEventListener(eventType, callbackFunction);
case 'change':
default:
this.radio.addEventListener(eventType, callbackFunction);
}
}
}
class TextFieldComponent {
constructor (element) {
this.input = element.querySelector('input[type="text"]');
this.label = element.querySelector('label');
}
get value () {
return this.input.value;
}
set value (newValue) {
this.input.dispatchEvent(new Event('focus'));
this.input.value = newValue;
this.input.dispatchEvent(new Event('keyup'));
this.input.dispatchEvent(new Event('change'));
this.input.dispatchEvent(new Event('blur'));
}
get text () {
return this.input.placeholder;
}
set text (newText) {
this.input.placeholder = newText;
}
addEventListener (eventType, callbackFunction) {
this.input.addEventListener(eventType, callbackFunction);
}
}
class GiftArrayButton extends RadioButtonComponent {
constructor (element) {
super(element);
}
get amount () {
return this.value;
}
set amount (newAmount) {
if (Number.isNaN(parseInt(newAmount)) || parseInt(newAmount) <= 0)
throw new Error("New amount must be a valid number greater than 0.");
newAmount = parseInt(newAmount);
this.text = '$' + newAmount;
this.value = newAmount;
}
}
class GiftArrayOtherAmount extends TextFieldComponent {
constructor (element) {
super(element);
}
get amount () {
return parseFloat(this.value);
}
set amount (newAmount) {
if (Number.isNaN(parseInt(newAmount)) || parseInt(newAmount) <= 0)
throw new Error("New amount must be a valid number greater than 0.");
newAmount = parseFloat(newAmount);
this.value = newAmount;
this.input.dispatchEvent(new Event('updateSummary'));
}
}
class GiftArray extends Array {
constructor (items) {
if (!Array.isArray(items) && items.length === 0) {
throw new Error("GiftArray: Arugment 1 is not an instance of Array with a length greater than 0:" + items.join(', '));
}
if (items.every((item) => item instanceof GiftArrayButton || item instanceof GiftArrayOtherAmount)) {
if (items.find((item) => item instanceof GiftArrayOtherAmount)) {
let temp = items.find((item) => item instanceof GiftArrayOtherAmount);
items = items.filter((item) => item instanceof GiftArrayButton);
items.push(temp);
}
} else if (items.every((item) => item instanceof HTMLElement)) {
items = items.map((item) => item.matches(".webform-component-textfield") ? new GiftArrayOtherAmount(item) : new GiftArrayButton(item));
} else {
throw new Error("GiftArray: Arugment 1 is not of type HTMLElement, HTMLElement[], or GiftArrayButton|GiftArrayButton[]:" + items.join(', '));
}
super(...items);
this.Buttons = items.filter((item) => item instanceof GiftArrayButton);
this.OtherAmountInput = items.find((item) => item instanceof GiftArrayOtherAmount);
}
get amount () {
const activeButton = this.Buttons.find((item) => item.checked);
if (activeButton.value === "other") {
const otherButton = activeButton;
if (!otherButton) {
throw new Error("GiftArray.amount: Other Button was not defined.");
}
otherButton.click();
return this.OtherAmountInput.value;
} else {
return activeButton.value;
}
}
set amount (newAmount) {
if (Number.isNaN(parseInt(newAmount)) || parseInt(newAmount) <= 0)
throw new Error("New amount must be a valid number greater than 0.");
newAmount = parseFloat(newAmount);
const matchingButton = this.find((item) => item.value === newAmount);
if (matchingButton) {
matchingButton.click();
} else {
const otherButton = this.Buttons.find((item) => item.value === "other");
otherButton.click();
this.OtherAmountInput.amount = newAmount;
}
}
addEventListeners (eventType, callbackFunction, filter = undefined) {
if (filter && typeof filter === 'function') {
const filteredItems = this.filter((item) => filter.call(this, item));
filteredItems.forEach((item) => item.addEventListener(eventType, callbackFunction));
} else if (filter && typeof filter === 'string') {
if (filter.match(/buttons/gmi))
this.Buttons.forEach((item) => item.addEventListener(eventType, callbackFunction));
if (filter.match(/other/gmi))
this.OtherAmountInput.addEventListener(eventType, callbackFunction);
} else {
this.forEach((item) => item.addEventListener(eventType, callbackFunction));
}
}
}
class FrequencyButton extends RadioButtonComponent {
constructor (element) {
super(element);
}
get frequency () {
return this.text.match(/Monthly/gmi) ? "Monthly" : "One-Time";
}
set freqency (newAmount) {
if (Number.isNaN(parseInt(newAmount)) || parseInt(newAmount) <= 0)
throw new Error("New amount must be a valid number greater than 0.");
newAmount = parseInt(newAmount);
this.text = '$' + newAmount;
this.value = newAmount;
}
}
class FrequencyArray extends Array {
constructor (items) {
if (!Array.isArray(items) && items.length === 0) {
throw new Error("FrequencyArray: Arugment 1 is not an instance of Array with a length greater than 0:" + items.join(', '));
}
/*if (items.every((item) => item instanceof GiftArrayButton || item instanceof GiftArrayOtherAmount)) {
if (items.find((item) => item instanceof GiftArrayOtherAmount)) {
let temp = items.find((item) => item instanceof GiftArrayOtherAmount);
items = items.filter((item) => item instanceof GiftArrayButton);
items.push(temp);
}
} else*/ if (items.every((item) => item instanceof HTMLElement)) {
items = items.map((item) => item.matches(".webform-component-textfield") ? new GiftArrayOtherAmount(item) : new GiftArrayButton(item));
} else {
throw new Error("FrequencyArray: Arugment 1 is not of type HTMLElement or HTMLElement[]:" + items.join(', '));
}
super(...items);
this.Buttons = items.filter((item) => item instanceof GiftArrayButton);
}
get frequency () {
const activeButton = this.Buttons.find((item) => item.checked);
if (activeButton.value === "recurs")
return "monthly";
if (activeButton.value === "NO_RECURR")
return "one-time";
return activeButton.value;
}
set frequency (newFrequency) {
const reNewFrequencyValue = new RegExp(newFrequency, 'gmi');
const matchingButton = this.find((item) => item.value.match(reNewFrequencyValue) || item.text.match(reNewFrequencyValue));
matchingButton.click();
}
get recurring () {
return this.frequency === "monthly" ? true : false;
}
set recurring (bool) {
this.frequency = bool === true ? "monthly" : "one-time";
}
addEventListeners (eventType, callbackFunction, filter = undefined) {
if (filter && typeof filter === 'function') {
const filteredItems = this.filter((item) => filter.call(this, item));
filteredItems.forEach((item) => item.addEventListener(eventType, callbackFunction));
} else if (filter && typeof filter === 'string') {
if (filter.match(/buttons/gmi))
this.Buttons.forEach((item) => item.addEventListener(eventType, callbackFunction));
if (filter.match(/other/gmi))
this.OtherAmountInput.addEventListener(eventType, callbackFunction);
} else {
this.forEach((item) => item.addEventListener(eventType, callbackFunction));
}
}
}
//
const lockedProperty = { writable: false, configurable: false, enumerable: true };
function DonationFormAPI (elements, options = {}) {
const defaultOptions = {
min: 1.00,
max: 999999.99,
makeTabbed: false,
fakeSubmit: true,
overrideGiftArrayValues: false,
};
options = { ...defaultOptions, ...options };
//
const { frequencyRadios, submitButton, root } = elements;
const [ amountRadiosOnetime, amountRadiosMonthly ] = elements.amountRadios;
const oneTimeOtherAmountWrapper = amountRadiosOnetime.find((div) => !div.matches('.webform-component-textfield') || div.querySelector('input[type="text"]'));
const oneTimeRadioButtons = amountRadiosOnetime.filter((div) => div !== oneTimeOtherAmountWrapper);
const monthlyOtherAmountWrapper = amountRadiosMonthly.find((div) => !div.matches('.webform-component-textfield') || div.querySelector('input[type="text"]'));
const monthlyRadioButtons = amountRadiosMonthly.filter((div) => div !== monthlyOtherAmountWrapper);
const debug = {
log: (...args) => window.NA.DonationForm.DEBUG_MODE && console.log(...args),
info: (...args) => window.NA.DonationForm.DEBUG_MODE && console.log(...args),
warn: (...args) => window.NA.DonationForm.DEBUG_MODE && console.log(...args),
error: (...args) => window.NA.DonationForm.DEBUG_MODE && console.log(...args),
};
//
const api = new Object();
Object.defineProperty(api, 'root', {
value: root,
writable: false,
configurable: true,
enumerable: true,
});
Object.defineProperties(api, {
'FORM_MINIMUM': {
value: options.min || 0,
...lockedProperty
},
'FORM_MAXIMUM': {
value: options.max || Infinity,
...lockedProperty
},
});
Object.defineProperties(api, {
GiftArrays: {
value: {
"one-time": new GiftArray([ ...oneTimeRadioButtons, oneTimeOtherAmountWrapper ]),
"monthly": new GiftArray([ ...monthlyRadioButtons, monthlyOtherAmountWrapper ]),
},
writable: false,
configurable: true,
enumerable: true,
},
Frequencies: {
value: new FrequencyArray(frequencyRadios),
writable: false,
configurable: true,
enumerable: true,
},
SubmitButton: {
value: submitButton,
writable: false,
configurable: false,
enumerable: true,
}
});
Object.defineProperties(api, {
'getFrequency': {
value: async function () {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise((resolve, reject) => {
try {
resolve(this.Frequencies.frequency);
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
'setFrequency': {
value: async function (frequency) {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise(async (resolve, reject) => {
try {
this.Frequencies.frequency = frequency;
if (await this.getFrequency() === frequency)
resolve(frequency);
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
'getAmount': {
value: async function (frequency = undefined) {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise(async (resolve, reject) => {
try {
frequency = frequency || await this.getFrequency();
if (frequency && this.GiftArrays.hasOwnProperty(frequency)) {
const activeGiftArray = this.GiftArrays[frequency];
resolve(activeGiftArray.amount);
} else {
throw new Error("getAmount: Invalid frequency: " + frequency);
}
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
'setAmount': {
value: async function (amount, frequency = undefined) {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise(async (resolve, reject) => {
try {
const currentFrequency = await this.getFrequency();
if (!frequency) {
frequency = currentFrequency;
} else if (frequency !== currentFrequency) {
frequency = await this.setFrequency(frequency);
}
if (frequency && this.GiftArrays.hasOwnProperty(frequency)) {
const activeGiftArray = this.GiftArrays[frequency];
activeGiftArray.amount = amount;
} else {
throw new Error("setAmount: Invalid frequency: " + frequency);
}
if (await this.getAmount() === amount)
resolve(amount);
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
'getRecurring': {
value: async function () {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise((resolve, reject) => {
try {
resolve(this.Frequencies.recurring);
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
'setRecurring': {
value: async function (bool) {
if (!this || this === null) throw new Error("validate: Unable to read API context.");
return new Promise(async (resolve, reject) => {
try {
this.Frequencies.frequency = bool ? true : false;
if (await this.getRecurring() === bool)
resolve(bool);
} catch (error) {
reject(error);
}
});
}, ...lockedProperty
},
freqency: {
get () { return this.getFrequency() },
set (value) { this.setFrequency(value) },
enumerable: true, configurable: true,
},
amount: {
get () { return this.getAmount() },
set (value) { this.setAmount(value) },
enumerable: true, configurable: true,
},
recurring: {
get () { return this.getRecurring() },
set (value) { this.setRecurring(value) },
enumerable: true, configurable: true,
},
});
Object.defineProperties(api, {
'submit': {
value: async function (condition = this.validate||function(){return true}) {
//this.hooks['onBeforeSubmit'].forEach((callback) => callback.call(this));
let result;
const isAsyncFunction = (func) => func.constructor.name === "AsyncFunction";
if (Array.isArray(condition)) {
if (condition.every((c) => typeof c === 'function' && isAsyncFunction(c))) {
result = await Promise.all(condition.map(async (c) => await c.call(this)));
} else if (condition.every((c) => typeof c === 'function')) {
result = condition.every((c) => c.call(this));
} else if (condition.every((c) => c === true || c === false)) {
result = condition.every((c) => c);
}
} else if (typeof condition === 'function' && isAsyncFunction(condition)) {
result = await condition.call(this);
} else if (typeof condition === 'function') {
result = condition.call(this);
} else if (condition === true || condition === false) {
result = condition;
} else {
console.error("Unknown error.");
debugger;
}
//
if (result === true) {
if (window.NA.DonationForm.hasOwnProperty("DEBUG_MODE") && window.NA.DonationForm["DEBUG_MODE"] == true)
return console.log("Submit aborted (debug mode is enabled).");
this.SubmitButton.click(),
this.hooks['onSubmit'].forEach((callback) => callback.call(this));
//this.hooks['onAfterSubmit'].forEach((callback) => callback.call(this));
} else {
return console.log("Submit failed (conditions did not evaluate to true).");
}
}, ...lockedProperty
},
'interceptSubmit': {
value: function (handleInterceptedSubmit = () => { return new Promise((resolve) => resolve(undefined)) }) {
try {
window.NA.DonationForm.SubmitButtonCopy = window.NA.DonationForm.SubmitButtonCopy || createNewSubmitButton(window.NA.DonationForm.SubmitButton, { cloneOriginal: false, hideOriginal: true, observeOriginal: false });
window.NA.DonationForm.SubmitButtonCopy.addEventListener('click', async (event) => {
event.preventDefault(), event.stopPropagation();
const shouldFormSubmit = await handleInterceptedSubmit.call(this, event);
if (shouldFormSubmit) {
console.info("Submit allowed by initial interceptSubmit callback function resulting in a truthy evaluation.");
const formIsValid = await window.NA.DonationForm.validate();
if (!formIsValid) { // if submit allowed but there are known errors in the form
console.warn("Form has known errors. Attempting to submit to show errors then retrying.");
console.log("Submitting...");
window.NA.DonationForm.submit(true); // submit anyway to trigger the error to be shown
window.NA.DonationForm.SubmitButton.style.setProperty("display", "none"), debug.info("SubmitButton hidden."), // hide the original submit button again
window.NA.DonationForm.SubmitButtonCopy.style.setProperty("display", "none"), debug.info("SubmitButtonCopy hidden."); // hide the copy of the submit button again
window.NA.DonationForm.SubmitButtonCopy.style.removeProperty("display"), debug.info("SubmitButtonCopy unhidden."); // show the copy of the submit button
} else {
console.log("Submitting...");
window.NA.DonationForm.submit(true);
}
} else {
console.log("Submit prevented.");
console.info("Next submit will be allowed.");
window.NA.DonationForm.SubmitButton.style.removeProperty("display"), debug.info("SubmitButton unhidden."); // show the original submit button so that if something goes wrong the user can still click the submit button
window.NA.DonationForm.SubmitButtonCopy.style.setProperty("display", "none"), debug.info("SubmitButtonCopy hidden."); // hide the copy of the submit button that intercepts submit attempts so that there aren't two buttons
}
});
console.log("Submit intercept added.\nButton:", window.NA.DonationForm.SubmitButtonCopy);
} catch (error) {
console.error("Failed to add submit intercept:", error);
}
}, ...lockedProperty
},
'validate': {
value: async function (root = undefined) {
if (!this || this === null)
throw new Error("validate: Unable to read API context.");
root = root || this.root;
const flattenArray = (array) => array.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? flattenArray(toFlatten) : toFlatten), []);
try {
const freqency = await this.getFrequency(),
amount = await this.getAmount();
if (!freqency || !amount)
return false;
if (amount < this.FORM_MINIMUM || amount > this.FORM_MAXIMUM)
return console.error("validate:", "Gift amount is invalid:", amount), false;
let requiredFields = Array.from(root.querySelectorAll('label:has(.form-required)'))
.map((label) => document.getElementById(label.htmlFor) || (label.nextElementSibling || label.previousElementSibling))
.filter((_) => !!_) // remove blanks
.filter((field) => {
if (field.name && field.name.includes('[payment_information]'))
return false;
return true;
})
.map((field) => {
if (field.matches("div"))
return [...field.querySelectorAll('input')];
return field;
})
requiredFields = flattenArray(requiredFields);
const valid = requiredFields.every((input) => {
const type = input.tagName.toLowerCase() === 'select' ? 'select' : input.type;
const { name, value, id } = input;
//console.log(type, name, value);
if (name === 'submitted[payment_information][payment_fields][credit][card_number]') {
if (value && value.length === 16)
return true;
return console.error("validate:", name+':', "CC is invalid."), false;
}
if (name === 'submitted[leadership_circle]')
return true;
if (name === 'submitted[donation][other_amount]' || name === 'submitted[donation][recurring_other_amount]')
if (amount)
return true;
switch (type) {
case 'email':
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
if (!emailRegex.test(value))
return console.error("validate:", name+':', "Email address is invalid.\n", input, value), false;
return true;
case 'tel':
if (!value || value.length < 10)
return console.error("validate:", name+':', "Phone number is invalid.\n", input, value), false;
return true;
case 'select':
case 'radio':
case 'text':
if (!value || value.length === 0)
return console.error("validate:", name+':', "Field is invalid.\n", input, value), false;
return true;
default:
debug.log("default");
return true;
}
/*if (!value || value.length === 0)
return false;*/
});
return valid;
} catch (error) {
console.error(error);
return false;
}
}, ...lockedProperty
},
//'makeTabbed': { value: function(){} },
'DonationInterrupter': {
value: { init: initDonationInterrupter.bind(api) },
enumerable: true,
configurable: true,
writable: true,
}
});
initHooks(api, ['onFrequencyChange', 'onAmountChange', 'onTrySubmit', 'onSubmit']);
api.Frequencies.addEventListeners('change', (event) => {
if (event.target.checked) {
api.hooks['onFrequencyChange'].forEach((callback) => {
callback.call(api, event.target.value);
});
}
});
Object.entries(api.GiftArrays).forEach(([ key, GiftArray ]) => {
GiftArray.addEventListeners('change', (event) => {
if (event.target.checked) {
api.hooks['onAmountChange'].forEach((callback) => {
callback.call(api, event.target.value);
});
}
});
});
api.SubmitButton.addEventListener('click', (event) => {
api.hooks['onTrySubmit'].forEach((callback) => callback.call(api, event));
});
api.root.addEventListener('submit', (event) => {
api.hooks['onSubmit'].forEach((callback) => callback.call(api, event));
});
if (options.makeTabbed)
api.makeTabbed();
/*if (options.fakeSubmit)
window.NA.DonationForm.SubmitButtonCopy = window.NA.DonationForm.SubmitButtonCopy || createNewSubmitButton(window.NA.DonationForm.SubmitButton, { cloneOriginal: false, hideOriginal: true, observeOriginal: false });*/
return api;
}
function createNewSubmitButton (originalSubmitButton = window.NA.DonationForm.SubmitButton, options = {}) {
const defaultOptions = {
cloneOriginal: true,
hideOriginal: true,
observeOriginal: true,
};
options = { ...defaultOptions, ...options };
const newSubmitButton = document.createElement('button');
//newSubmitButton.id = "submit-button-copy";
newSubmitButton.classList.add("btn");
newSubmitButton.textContent = originalSubmitButton.value;
originalSubmitButton.after(newSubmitButton);
options.hideOriginal && originalSubmitButton.style.setProperty("display", "none");
return newSubmitButton;
}
function initHooks (api, hookNames = []) {
const hooks = Object.fromEntries(hookNames.map((hookName) => ([hookName, new Array()])));
Object.defineProperty(api, 'hooks', {
value: hooks,
...lockedProperty
});
}
function initDonationInterrupter (options = {}) {
const getExpId = () => {
let experiments = window._vwo_exp;
experiments = Object.entries(window._vwo_exp);
let id = experiments.find(([id, data]) => {
const name = data.name;
return name.match(/Donation Interrupter/);
})[1]?.id;
return id;
};
const getExpVariation = (id) => {
let experiment = window._vwo_exp[id];
return experiment.combination_chosen || experiment.combination_selected;
};
const defaultOptions = {
id: [ 'VWO', getExpId(), getExpVariation(getExpId()) ].join('-'),
tokenName: ("NA__MPR_DonationInterrupter:" + [ 'VWO', getExpId(), getExpVariation(getExpId()) ].join('-')),
min: 10,
max: 100,
askAmount: (originalAmount) => {
if (originalAmount > 500) // $500+
return false; // don't show
if (originalAmount >= 400) // $400-$500
return 50;
if (originalAmount >= 300) // $300-$399
return 40;
if (originalAmount >= 200) // $200-$299
return 30;
if (originalAmount >= 100) // $100-$199
return 15;
if (originalAmount < 100) // $100-
return 10;
return false;
},
askFrequency: (originalFrequency) => {
return "monthly";
},
popupHTML: {
headingHTML: (`
Lorem ipsum dolor sit amet
`),
bodyHTML: (`
Consectetur adipiscing elit. Sed nec egestas turpis, hendrerit semper nisl. Pellentesque auctor ipsum at
pharetra eleifend. Pellentesque a rhoncus turpis, ut tempus nibh. Donec vel dui hendrerit nisi imperdiet
tincidunt. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
Duis efficitur dolor ut nisl blandit imperdiet. Nullam pretium est nunc, tincidunt viverra ligula dapibus.
Duis malesuada:
dui eu venenatis volutpat
urna libero posuere lectus
non tincidunt mauris ligula consectetur felis
lacinia hendrerit enim at molestie
Sed placerat fringilla consequat. Nullam eu pellentesque sem?
`;
document.body.appendChild(dialogElement);
//
//
const api = new Object({
askAmount: options.askAmount,
askFrequency: options.askFrequency,
});
Object.defineProperties(api, {
id: {
value: options.id,
writable: false, enumerable: true, configurable: false,
},
tokenName: {
value: options.tokenName,
writable: false, enumerable: true, configurable: false,
},
Dialog: {
value: dialogElement,
writable: false, enumerable: true, configurable: true,
},
show: {
value: function () {
this.update(),
this.Dialog.showModal(),
vwoCustomEvent(`${this.id}:shown`);
this.storedState.updateTokenProperty("lastShown", getCurrentDate());
this.hooks['onShow'].forEach((callback) => callback.call(this));
}, ...lockedProperty
},
hide: {
value: function () {
this.Dialog.close(),
this.hooks['onHide'].forEach((callback) => callback.call(this));
}, ...lockedProperty
},
update: {
value: function () {
this.Dialog.dispatchEvent(new CustomEvent('update'), { bubbles: false });
}, ...lockedProperty
}
});
Object.defineProperty(api, 'storedState', {
value: {
storageApi: localStorage,
getToken: (function () {
const tokenName = this.tokenName,
storageApi = this.storedState.storageApi;
return JSON.parse(storageApi.getItem(tokenName)) || null;
}).bind(api),
setToken: (function (tokenValue) {
const tokenName = this.tokenName,
storageApi = this.storedState.storageApi;
return storageApi.setItem(tokenName, JSON.stringify(tokenValue));
}).bind(api),
updateTokenProperty: (function (tokenPropertyName, tokenPropertyValue) {
let state = this.storedState.getToken() || {};
state[tokenPropertyName] = tokenPropertyValue;
this.storedState.setToken(state);
return (this.storedState.getToken() || {})[tokenPropertyName] || undefined;
}).bind(api),
}
});
initHooks(api, ['onShow', 'onHide', 'onUpdate', 'onYes', 'onNo']);
function handleDialogUpdate (event) { // update dynamic text in the dialog
Array.from(this.Dialog.querySelectorAll('[data-value]')).forEach(async (el) => {
const attributeValue = el.getAttribute('data-value');
const currentAmount = await window.NA.DonationForm.getAmount(),
currentFrequency = await window.NA.DonationForm.getFrequency();
if (attributeValue.match("askAmount")) {
el.textContent = this.askAmount(currentAmount);
} else if (attributeValue.match("askFrequency")) {
el.textContent = this.askFrequency(currentFrequency);
} else if (attributeValue.match("originalAmount") || attributeValue.match("amount")) {
el.textContent = currentAmount;
} else if (attributeValue.match("originalFrequency") || attributeValue.match("frequency")) {
el.textContent = currentFrequency;
}
});
this.hooks['onUpdate'].forEach((callback) => callback.call(this));
}
api.Dialog.addEventListener('update', handleDialogUpdate.bind(api));
//
const handleYes = (async function () {
vwoCustomEvent(`${this.id}:DonationInterrupter:yes`);
const currentAmount = await window.NA.DonationForm.getAmount(),
currentFrequency = await window.NA.DonationForm.getFrequency();
const catchAsyncError = (error) => { console.error("An error occured:", error); debugger; this.hide(); };
window.NA.DonationForm.setFrequency(this.askFrequency(currentFrequency)).then((frequency) => {
console.log("Updated frequency:", frequency);
window.NA.DonationForm.setAmount(this.askAmount(currentAmount)).then((amount) => {
console.log("Updated amount:", amount);
setTimeout(() => {
console.log("Submitting...");
try {
window.NA.DonationForm.submit();
} catch (error) {
console.error("Error when submitting.");
} finally {
this.hide();
}
}, 100);
}).catch(catchAsyncError);
}).catch(catchAsyncError);
this.storedState.updateTokenProperty("lastConverted", getCurrentDate());
}).bind(api);
const handleNo = (function () {
vwoCustomEvent(`${this.id}:DonationInterrupter:no`);
setTimeout(() => {
console.log("Submitting...");
try {
window.NA.DonationForm.submit();
} catch (error) {
console.error("Error when submitting.");
} finally {
this.hide();
}
}, 100);
this.storedState.updateTokenProperty("lastDismissed", getCurrentDate());
}).bind(api);
const handleCancel = (function () {
this.hide();
this.storedState.updateTokenProperty("lastDismissed", getCurrentDate());
}).bind(api);
async function handleDialogButtonClick (event) {
event.preventDefault();
if (event.target.hasAttribute('data-action')) {
if (event.target.getAttribute('data-action').match("yes")) {
await handleYes.call(this);
this.hooks['onYes'].forEach((callback) => callback.call(this));
}
if (event.target.getAttribute('data-action').match("no")) {
await handleNo.call(this);
this.hooks['onNo'].forEach((callback) => callback.call(this));
}
}
}
Array.from(api.Dialog.querySelectorAll('.popup__footer button')).forEach((button) => button.addEventListener('click', handleDialogButtonClick.bind(api)));
if (api.Dialog.querySelector('.btn-dismiss'))
api.Dialog.querySelector('.btn-dismiss').onclick = handleCancel;
window.NA.DonationForm.DonationInterrupter = api;
async function shouldDonationInterrupterShow () {
return new Promise(async (resolve, reject) => {
const shouldSubmit = true,
shouldNotSubmit = false;
const shouldShow = () => { this.show(), resolve(shouldNotSubmit) },
shouldNotShow = () => resolve(shouldSubmit);
try {
const formIsValid = await window.NA.DonationForm.validate();
if (!formIsValid)
return console.log("One or more donation form fields are invalid; donation interrupter will not be shown."),
shouldNotShow();
const currentFrequency = await window.NA.DonationForm.getFrequency(),
currentAmount = await window.NA.DonationForm.getAmount(),
askFrequency = this.askFrequency(currentFrequency),
askAmount = this.askAmount(currentAmount);
if (!currentFrequency || askFrequency == currentFrequency)
return console.log("Ask frequency returned false or invalid; donation interrupter will not be shown."),
shouldNotShow();
if (askAmount == false || askAmount <= 0)
return console.log("Ask amount returned false or invalid; donation interrupter will not be shown."),
shouldNotShow();
} catch (error) {
return console.error(error),
shouldNotShow();
}
try {
/// Summary: shows when not seen before at all, or if seen and dismissed on a day that is not the current day (e.g. yesterday)
const storedState = this.storedState.getToken();
if (!storedState || !storedState.hasOwnProperty("lastShown")) { // has not been seen before; first time
return console.log("Donation interrupter not seen yet; donation interrupter will be shown."),
shouldShow();
} else { // returning visitors
if (storedState.hasOwnProperty("lastConverted")) { // the user has converted from the popup before
return console.log("Already converted; donation interrupter will not be shown."),
shouldNotShow();
}
else if (storedState.hasOwnProperty("lastDismissed") && storedState['lastDismissed'] !== getCurrentDate()) { // if the popup has been dismissed before but the last time it was dismissed is NOT today
return console.log("Donation interrupter dismissed, but not today; donation interrupter will be shown."),
shouldShow();
}
else {
return console.log("Donation interrupter already seen and/or dismissed today; donation interrupter will not be shown."),
shouldNotShow();
}
}
} catch (error) {
return console.error(error),
shouldNotShow();
}
});
}
window.NA.DonationForm.interceptSubmit(shouldDonationInterrupterShow.bind(api));
resolve(api);
} catch (error) {
console.error(error);
}
});
}
window.NA = window.NA || {};
window.NA.DonationForm = window.NA.DonationForm || {};
window.NA.DonationForm.init = async function init () {
console.log("Initializing donation form API. Waiting for required elements....");
return new Promise((resolve, reject) => {
const asyncWaitForElement=async function(e,r=100,t=1e4){r=Number.isInteger(r)&&r>0&&r<=100?r:parseInt(r);let n="Array";if("NaN"==r)return console.error("Invalid refresh interval:",r);Array.isArray(e)||"string"!=typeof e||(n="string",e=[e]);let l=e=>document.querySelector(e),i=e=>e.every(e=>!!l(e));return new Promise((R,a)=>{let m=(e,r=null)=>(r&&clearInterval(r),R("Array"==n||e.length>1?e.map(e=>l(e)):l(e[0]))),o=n=>{console.error(`${n.name}: ${n.message}`);let l=()=>asyncWaitForElement(e,r=100,t=1e4);return a(n,l)};try{if(i(e))return m(e);let s=setInterval(()=>{if(i(e))return m(e,s)},1e3/r);setTimeout(()=>{try{if(!i(e)){clearInterval(s);let r=Error(`Failed to find matching elements within ${t}ms`);throw r.name="Timed Out",r}}catch(n){return o(n)}},t)}catch(u){return o(u)}})};
asyncWaitForElement([ 'form.webform-client-form', '#webform-component-donation--recurs-monthly', '#webform-component-donation--amount', '#webform-component-donation--recurring-amount', '.form-actions input[type="submit"]' ]).then(([ componentDonationForm, componentFrequency, componentAmountOnetime, componentAmountMonthly, formSubmitButton ]) => {
const api = DonationFormAPI({
root: componentDonationForm,
frequencyRadios: [...componentFrequency.querySelectorAll('.form-type-radio')],
amountRadios: [
[...componentAmountOnetime.querySelectorAll('div > .form-type-radio, div > .webform-component-textfield')],
[...componentAmountMonthly.querySelectorAll('div > .form-type-radio, div > .webform-component-textfield')],
],
submitButton: formSubmitButton,
//
});
window.NA.DonationForm = { ...window.NA.DonationForm, ...api };
resolve(window.NA.DonationForm);
}).catch((error) => reject(error));
});
};
}catch(e) {console.error(e)}
return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, R_940895_39_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
try{
var ctx=vwo_$(x),el;
/*vwo_debug log("Revert","content",""); vwo_debug*/;
el=vwo_$('[vwo-element-id="1740425171461"]');
el.revertContentOp().remove();
} catch(e) {console.error(e)}
try{
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","addElement","body"); vwo_debug*/(el=vwo_$('[vwo-element-id="1740425171462"]')).remove();
} catch(e) {console.error(e)}
return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, C_940895_54_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("remove","H1:tm('Support MPR News Today!')"); vwo_debug*/(el=vwo_$("H1:tm('Support MPR News Today!')")).vwoCss({display:"none !important"});})("H1:tm('Support MPR News Today!')")}}, C_940895_39_1_2_1:{ fn:function(log,nonce=''){return (function(x) {
try{
var _vwo_sel = vwo_$("`);
!vwo_$("head").find('#1740425171462').length && vwo_$('head').append(_vwo_sel);}catch(e) {console.error(e)}
try{}catch(e) {console.error(e)}
try{const DONATION_INTERRUPTER_OPTIONS = {
headingSectionHTML: (`
Before you go, would you consider becoming a sustainer to MPR News?
`),
bodySectionHTML: (`
Your monthly gift supports trusted journalism, music discovery, and community
conversation for all – no matter where you live or how you listen. From the
broadcast to the podcast, on-air and online, gifts from individuals power everything
you find at Minnesota Public Radio.
Would you consider becoming a sustainer by converting your one-time gift to a
monthly gift today?
`),
min: 100, // do not show if original gift is below this amount
max: 500, // do not show if original gift is above this amount
askAmount: (originalAmount) => {
// the input is the original amount
// the output is the ask amount, or false if the input does not map to an ask amount
if (originalAmount > 500.00) // $500+
return false; // don't show
if (originalAmount >= 400.00) // $400-$500
return 50.00;
if (originalAmount >= 300.00) // $300-$399
return 40.00;
if (originalAmount >= 200.00) // $200-$299
return 30.00;
if (originalAmount >= 100.00) // $100-$199
return 15.00;
if (originalAmount < 100.00) // $100-
return 10.00;
return false;
},
};
//
//
//
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
//
//
//
window.NA.DonationForm.init({ makeTabbed: false }).then(async (donationFormApi) => {
//console.log("DonationForm:", donationFormApi);
console.log("Donation Form: %c READY %c", 'background-color: MediumSeaGreen; color: white; font-weight: bold;', 'background-color: unset; color: unset; font-weight: unset;');
console.log(donationFormApi);
const interrupter = await donationFormApi.DonationInterrupter.init({
min: DONATION_INTERRUPTER_OPTIONS.min,
max: DONATION_INTERRUPTER_OPTIONS.max,
askAmount: DONATION_INTERRUPTER_OPTIONS.askAmount,
popupHTML: {
headingHTML: DONATION_INTERRUPTER_OPTIONS.headingSectionHTML,
bodyHTML: DONATION_INTERRUPTER_OPTIONS.bodySectionHTML,
},
});
//console.log("DonationInterrupter", interrupter);
console.log("Donation Interrupter: %c READY %c", 'background-color: MediumSeaGreen; color: white; font-weight: bold;', 'background-color: unset; color: unset; font-weight: unset;');
console.log(interrupter);
//interrupter.show(); // debug: always show popup immediately when page loads
}).catch((error) => { console.log("Donation Interrupter: %c FAILED %c An error occured when initializing the API:", 'background-color: Tomato; color: white; font-weight: bold;', 'background-color: unset; color: Tomato; font-weight: unset;'), console.error(error) });
}catch(e) {console.error(e)}
return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, R_940895_48_1_2_4:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
})(".author,.img-wrapper,.img-wrapper img,.author-copy")}}, C_940895_61_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_75-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_75-L > b:nth-of-type(1)")).html("1. How frequently do you listen to Minnesota Public Radio?");})("#tfa_75-L > b:nth-of-type(1)")}}, R_940895_61_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_75-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_75-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_75-L > b:nth-of-type(1)")}}, C_940895_61_1_2_1:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_87-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_87-L > b:nth-of-type(1)")).html("2. Which MPR programs or segments do you listen to most often?");})("#tfa_87-L > b:nth-of-type(1)")}}, R_940895_61_1_2_1:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_87-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_87-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_87-L > b:nth-of-type(1)")}}, C_940895_61_1_2_2:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_81-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_81-L > b:nth-of-type(1)")).html("3. How Satisfied are you with the programs and offerings provided by MPR?");})("#tfa_81-L > b:nth-of-type(1)")}}, R_940895_61_1_2_2:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_81-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_81-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_81-L > b:nth-of-type(1)")}}, R_940895_61_1_2_3:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_93-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_93-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_93-L > b:nth-of-type(1)")}}, C_940895_61_1_2_4:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_102-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_102-L > b:nth-of-type(1)")).html("5. Which topics or issues are you most interested in hearing about on MPR?");})("#tfa_102-L > b:nth-of-type(1)")}}, R_940895_61_1_2_4:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_102-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_102-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_102-L > b:nth-of-type(1)")}}, C_940895_61_1_2_5:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_112-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_112-L > b:nth-of-type(1)")).html("6. How likely are you to recommend MPR to a friend or family member?");})("#tfa_112-L > b:nth-of-type(1)")}}, R_940895_61_1_2_5:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_112-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_112-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_112-L > b:nth-of-type(1)")}}, C_940895_61_1_2_6:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_118-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_118-L > b:nth-of-type(1)")).html("7. What is your overall impression of the quality of MPR's programs and offering?");})("#tfa_118-L > b:nth-of-type(1)")}}, R_940895_61_1_2_6:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_118-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_118-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_118-L > b:nth-of-type(1)")}}, C_940895_61_1_2_7:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_124-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_124-L > b:nth-of-type(1)")).html("8. How important is MPR to your ability to stay informed?");})("#tfa_124-L > b:nth-of-type(1)")}}, R_940895_61_1_2_7:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_124-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_124-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_124-L > b:nth-of-type(1)")}}, C_940895_61_1_2_8:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_130-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_130-L > b:nth-of-type(1)")).html("9. Do you believe that MPR is an important community resource?");})("#tfa_130-L > b:nth-of-type(1)")}}, R_940895_61_1_2_8:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_130-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_130-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_130-L > b:nth-of-type(1)")}}, C_940895_61_1_2_9:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("editElement","#tfa_134-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_134-L > b:nth-of-type(1)")).html("10. In your own words, why would an MPR listener choose to become a donor?");})("#tfa_134-L > b:nth-of-type(1)")}}, R_940895_61_1_2_9:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","editElement","#tfa_134-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_134-L > b:nth-of-type(1)")).vwoRevertHtml();})("#tfa_134-L > b:nth-of-type(1)")}}, C_940895_64_1_2_0:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x);
/*vwo_debug log("content","#tfa_134-L > b:nth-of-type(1)"); vwo_debug*/el=vwo_$("#tfa_134-L > b:nth-of-type(1)"),vwo_$("#tfa_134-L > b:nth-of-type(1)").each((function(){this.__vwoControlOuterHTML=this.__vwoControlOuterHTML||this.outerHTML,vwo_$(this).vwoAttr("class",""),!vwo_$(this).find('[vwo-op-1742933835357-1=""]').length&&vwo_$(this).append('(Optional)'),vwo_$(this).nonEmptyContents().eq(0).replaceWith2(document.createTextNode("In your own words, why would an Marketplace listener choose to become an donor? "))})),el=vwo_$("#tfa_134-L > b:nth-of-type(1)");})("#tfa_134-L > b:nth-of-type(1)")}}, R_940895_64_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","content","#tfa_134-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_134-L > b:nth-of-type(1)")).revertContentOp(),el=vwo_$("#tfa_134-L > b:nth-of-type(1)");})("#tfa_134-L > b:nth-of-type(1)")}}, R_940895_63_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
if(!vwo_$.fn.vwoRevertHtml){
return;
};
var el,ctx=vwo_$(x);
/*vwo_debug log("Revert","remove","#tfa_31-HTML > p:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_31-HTML > p:nth-of-type(1)")).vwoRevertCss(),(el=vwo_$('[vwo-element-id="1742589780114"]')).remove();})(".hintsBelow")}}, C_940895_16_1_2_0:{ fn:function(log,nonce=''){return (function(x) {
try{
var _vwo_sel = vwo_$("`);
!vwo_$("head").find('#1738257835657').length && vwo_$('head').append(_vwo_sel);}catch(e) {console.error(e)}
try{}catch(e) {console.error(e)}
try{const DEAR_READER_HEADING_HTML="
Dear reader,
",DEAR_READER_BODY_HTML="\n
Political debates with family or friends can get heated. But what if there was a way to handle them better?
\n
You can learn how to have civil political conversations with our new e-book!
\n
Download our free e-book, Talking Sense: Have Hard Political Conversations, Better, and learn how to talk without the tension.
\n",DEAR_READER_CTA_TEXT="Get your free ebook »",DEAR_READER_CTA_LINK="https://cloud.connect.mpr.org/mprnews-cfw03-01-talking-sense?utm_campaign=cfw_talkingsense&utm_term=dearreader_co";!function(){const e=async function(r,t=100,n=1e4){t=Number.isInteger(t)&&t>0&&t<=100?t:parseInt(t);let a="Array";if("NaN"==t)return console.error("Invalid refresh interval:",t);Array.isArray(r)||"string"!=typeof r||(a="string",r=[r]);let o=e=>document.querySelector(e),i=e=>e.every(e=>!!o(e));return new Promise((l,s)=>{let c=(e,r=null)=>(r&&clearInterval(r),l("Array"==a||e.length>1?e.map(e=>o(e)):o(e[0]))),d=a=>{console.error(`${a.name}: ${a.message}`);return s(a,()=>e(r,t=100,n=1e4))};try{if(i(r))return c(r);let e=setInterval(()=>{if(i(r))return c(r,e)},1e3/t);setTimeout(()=>{try{if(!i(r)){clearInterval(e);let r=Error(`Failed to find matching elements within ${n}ms`);throw r.name="Timed Out",r}}catch(e){return d(e)}},n)}catch(e){return d(e)}})};e("article").then(e=>{e.insertAdjacentHTML("beforeend",`
By submitting, you consent that you are at least 18 years of age and to receive information about MPR's or APMG entities' programs and offerings. The personally identifying information you provide will not be sold, shared, or used for purposes other than to communicate with you about MPR, APMG entities, and its sponsors. You may opt-out at any time clicking the unsubscribe link at the bottom of any email communication. View our Privacy Policy.
Knight Foundation awards $8M to support arts in St. Paul
The Saint Paul Chamber Orchestra during a rehearsal in a press photo. The SPCO is one of the city's arts organization that will benefit from an $8 million grant by the Knight Foundation.
The St. Paul arts scene received a huge shot in the arm today when the Miami-based Knight Foundation announced an $8 million grant to institutions and individuals to support the arts.
The Knight Foundation grant comes in two parts.
The first $3.5 million will go to five anchor institutions: the Saint Paul Chamber Orchestra, Penumbra Theater, Springboard for the Arts, TU Dance, and the Arts Partnership, the umbrella organization building the new concert hall at the Ordway Center.
"Those are the institutions that get up and do it every day," said Dennis Scholl, vice president of the Knight Foundation. "Some of them have been around for a while. Some of them are growing very rapidly, but they serve many, many people in the community."
The additional $4.5 million will be available to organizations and individuals who pitch ideas for arts projects in St Paul, as long as they meet the three criteria of the Arts Challenge.
Turn Up Your Support
MPR News helps you turn down the noise and build shared understanding. Turn up your support for this public resource and keep trusted journalism accessible to all.
To qualify, the ideas must be about art,and must take place in or benefit St Paul. Winning individuals and organizations also must find funds to match the foundation's grant.
The Knight Foundation works in 26 communities where the Knight brothers once owned newspapers, among them St. Paul. Similar grants will go to Miami, Philadelphia and Detroit.
Laura Zabel, executive director of Springboard for the Arts, which will receive $500,000, has watched what happened in those other cities, and sees great potential in her hometown, particularly from the challenge.
"It's a real statement that good ideas aren't tied to organizational structure or what your job title says you are," Zabal said. "It says that good ideas come from everywhere, and I think that's what the arts community really needs right now."
The grant will help the St Paul organization, a national leader in supporting artists, to work in seven other communities supported by the Knight Foundation. In St. Paul, Zabal expects the grant to produce a great deal of work which will be visible to everyone.
"It won't be just sort of shut away in a beautiful silo," she said. "It will be really integrated into the fabric of the community."
A number of the institutional grants are aimed at audience development. The SPCO will receive $1 million to increase its digital programming on the web and on mobile devices. TU Dance will receive $500,000 to offer classes and outreach programs to St Paul's diverse communities. The Art Partnerships will use its $1 million grant to subsidize productions by emerging arts groups at the Ordway. Penumbra Theater will receive $500,000 to hire two staff members to engage new donors and expand audiences.
Penumbra managing director Chris Widdess said the grant will be a game-changer, "not only because of its size, but because it's a multi-year gift."
Widdess said such grants are rare nowadays. The grant's five-year span gives Penumbra some breathing room. After almost collapsing, the company is implementing a new business plan aimed at long-term stability.
Co-Artistic director Sarah Bellamy said the Knight grant is well-timed for the whole of the city's arts scene.
"St Paul is a gem, and I think that investing in the arts organizations that are here will continue to create that eco-system that is flowering right now," she said.
Joe Spencer, director of arts and culture for St. Paul Mayor Chris Coleman, agreed.
"The timing of this money and the size of the commitment is absolutely going to be, if not transformative in and of itself, going to be a huge help at a transformative moment for our city," Spencer said.
While Spencer is delighted the grant is directed to St. Paul, he expects a ripple effect outside the city.
"Knight has a specific commitment to St Paul because of the history and the legacy here, but this is going to be good for the whole region," he said.
The Knight Foundation will begin taking applications for the challenge in early April.
Scholl, who read the 15,000 pitches from the three other cities, said he's looking forward to reading St Paul's ideas.
Dear reader,
Political debates with family or friends can get heated. But what if there was a way to handle them better?
You can learn how to have civil political conversations with our new e-book!
Download our free e-book, Talking Sense: Have Hard Political Conversations, Better, and learn how to talk without the tension.
News you can use in your inbox
When it comes to staying informed in Minnesota, our newsletters overdeliver. Sign-up now for headlines, breaking news, hometown stories, weather and much more. Delivered weekday mornings.