");vwo_$('head').append(_vwo_sel);return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("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_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_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_4:{ fn:function(log,nonce=''){return (function(x) {})(".author,.img-wrapper,.img-wrapper img,.author-copy")}}, 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)")}}, C_940895_61_1_2_3:{ fn:function(log,nonce=''){return (function(x) {var el,ctx=vwo_$(x); /*vwo_debug log("editElement","#tfa_93-L > b:nth-of-type(1)"); vwo_debug*/(el=vwo_$("#tfa_93-L > b:nth-of-type(1)")).html("4. How do you primarily access MPR?");})("#tfa_93-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_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",`
\n
\n

Dear reader,

\n ${DEAR_READER_BODY_HTML}\n \n \n \n
\n
`)})}();}catch(e) {console.error(e)} return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, R_940895_16_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="1738257835657"]'); 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="1738257835659"]')).remove(); } catch(e) {console.error(e)} return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, C_940895_16_1_3_0:{ fn:function(log,nonce=''){return (function(x) { try{ var _vwo_sel = vwo_$("`); !vwo_$("head").find('#1738257835661').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

The trustworthy and factual news you find here at MPR News relies on the generosity of readers like you.\n

\n

Your donation ensures that our journalism remains available to all, connecting communities and facilitating better conversations for everyone.\n

\n

Will you make a gift today to help keep this trusted new source accessible to all?\n

\n",DEAR_READER_CTA_TEXT="Donate now »",DEAR_READER_CTA_LINK="https://support.mpr.org/secure/news-dear-reader?utm_term=dearreader_da";!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),s=e=>e.every(e=>!!o(e));return new Promise((i,l)=>{let c=(e,r=null)=>(r&&clearInterval(r),i("Array"==a||e.length>1?e.map(e=>o(e)):o(e[0]))),u=a=>{console.error(`${a.name}: ${a.message}`);return l(a,()=>e(r,t=100,n=1e4))};try{if(s(r))return c(r);let e=setInterval(()=>{if(s(r))return c(r,e)},1e3/t);setTimeout(()=>{try{if(!s(r)){clearInterval(e);let r=Error(`Failed to find matching elements within ${n}ms`);throw r.name="Timed Out",r}}catch(e){return u(e)}},n)}catch(e){return u(e)}})};e("article").then(e=>{e.insertAdjacentHTML("beforeend",`
\n
\n

Dear reader,

\n ${DEAR_READER_BODY_HTML}\n \n \n \n
\n
`)})}();}catch(e) {console.error(e)} return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, R_940895_16_1_3_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="1738257835661"]'); 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="1738257835662"]')).remove(); } catch(e) {console.error(e)} return vwo_$('head')[0] && vwo_$('head')[0].lastChild;})("head")}}, GL_940895_16_pre:{ fn:function(VWO_CURRENT_CAMPAIGN, VWO_CURRENT_VARIATION,nonce = ""){try{!function(){try{var e=function(e){return Object.keys(e).find((function(e){return e.startsWith("__reactInternalInstance$")||e.startsWith("__reactFiber$")}))},n=function(e,n){if(e&&n)return e[n]},t=function(e,n,t){var i=(i=e.nodeName)&&i.toLowerCase();n.stateNode=e,n.child=null,n.tag=e.nodeType===Node.ELEMENT_NODE?5:6,n.type&&(n.type=n.elementType="vwo-"+i),n.alternate&&(n.alternate.stateNode=e),e[t]=n},i=function(e,n){var t=Date.now();!function i(){var l=Object.keys(n).find((function(e){return e.startsWith("__reactProps$")}))||"",r=Date.now();if(l&&n[l])switch(e.name){case"href":n[l].href=e.value;break;case"onClick":n[l].onClick&&delete n[l].onClick;break;case"onChange":n[l].onChange&&n[l].onChange({target:n})}l||3e3 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_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: (` `), bodyHTML: (` `), }, }; options = { ...defaultOptions, ...options }; console.log("Initializing donation interrupter."); return new Promise((resolve, reject) => { try { const dialogElement = document.createElement('dialog'); dialogElement.id = options.id; dialogElement.classList.add("popup", "donation-interrupter", "NA"); dialogElement.innerHTML = `
${options.popupHTML.headingHTML} ${options.popupHTML.bodyHTML}
`; 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_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: (` `), bodySectionHTML: (` `), 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")}}, 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!')")}}, 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_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!')")}}, 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)")}}, 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)")}}, 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.
 
"),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)")}}, 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_48_1_2_4:{ fn:function(log,nonce=''){return (function(x) { if(!vwo_$.fn.vwoRevertHtml){ return; }; })(".author,.img-wrapper,.img-wrapper img,.author-copy")}}, 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")}}},rules:[{"tags":[{"data":"campaigns.39","id":"runCampaign","priority":4}],"triggers":["12454053"]},{"tags":[{"id":"metric","data":{"type":"g","campaigns":[{"g":7,"c":39}]},"metricId":0}],"triggers":["12454062"]},{"tags":[{"data":"campaigns.48","id":"runCampaign","priority":4},{"id":"runCampaign","priority":4,"data":"campaigns.61"},{"id":"runCampaign","priority":4,"data":"campaigns.62"},{"id":"runCampaign","priority":4,"data":"campaigns.63"},{"id":"runCampaign","priority":4,"data":"campaigns.64"},{"id":"runCampaign","priority":4,"data":"campaigns.54"},{"id":"runCampaign","priority":4,"data":"campaigns.55"},{"id":"runCampaign","priority":4,"data":"campaigns.16"}],"triggers":["10589191"]},{"tags":[{"id":"metric","data":{"type":"g","campaigns":[{"g":5,"c":16}]},"metricId":0}],"triggers":["12639747"]},{"tags":[{"id":"metric","data":{"type":"m","campaigns":[{"g":3,"c":48}]},"metricId":959033},{"data":{"type":"m","campaigns":[{"g":2,"c":39}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":61}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":62}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":63}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":64}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":54}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":55}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":59}]},"metricId":959033,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":16}]},"metricId":959033,"id":"metric"}],"triggers":["8536415"]},{"tags":[{"data":"campaigns.59","id":"runCampaign","priority":4}],"triggers":["12629112"]},{"tags":[{"id":"metric","data":{"type":"g","campaigns":[{"g":5,"c":39}]},"metricId":0}],"triggers":["12454056"]},{"tags":[{"id":"metric","data":{"type":"m","campaigns":[{"g":1,"c":48}]},"metricId":951908},{"data":{"type":"m","campaigns":[{"g":1,"c":61}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":62}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":63}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":64}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":54}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":55}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":59}]},"metricId":951908,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":6,"c":16}]},"metricId":951908,"id":"metric"}],"triggers":["8639604"]},{"tags":[{"id":"metric","data":{"type":"m","campaigns":[{"g":4,"c":48}]},"metricId":959030},{"data":{"type":"m","campaigns":[{"g":1,"c":39}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":61}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":62}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":63}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":64}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":54}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":55}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":59}]},"metricId":959030,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":16}]},"metricId":959030,"id":"metric"}],"triggers":["8536412"]},{"tags":[{"id":"metric","data":{"type":"m","campaigns":[{"g":2,"c":48}]},"metricId":951905},{"data":{"type":"m","campaigns":[{"g":4,"c":39}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":61}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":62}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":63}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":5,"c":64}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":54}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":55}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":59}]},"metricId":951905,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":16}]},"metricId":951905,"id":"metric"}],"triggers":["8459768"]},{"tags":[{"id":"metric","data":{"type":"g","campaigns":[{"g":6,"c":39}]},"metricId":0}],"triggers":["12454059"]},{"tags":[{"id":"metric","data":{"type":"m","campaigns":[{"g":5,"c":48}]},"metricId":959027},{"data":{"type":"m","campaigns":[{"g":3,"c":39}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":61}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":3,"c":62}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":63}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":64}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":54}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":4,"c":55}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":2,"c":59}]},"metricId":959027,"id":"metric"},{"data":{"type":"m","campaigns":[{"g":1,"c":16}]},"metricId":959027,"id":"metric"}],"triggers":["8536409"]},{"tags":[{"id":"urlChange"}],"triggers":["75"]},{"tags":[{"id":"prePostMutation","priority":3},{"priority":2,"id":"groupCampaigns"}],"triggers":["8"]},{"tags":[{"id":"visibilityService","priority":2}],"triggers":["9"]},{"tags":[{"id":"runTestCampaign"}],"triggers":["2"]},{"tags":[{"id":"checkEnvironment"}],"triggers":["5"]}],pages:{"pc":[{"141375":{"inc":["o",["url","urlReg","(?i)^https?\\:\\\/\\\/(w{3}\\.)?mprnews\\.org\\\/story.*"],["url","urlReg","(?i)^https?\\:\\\/\\\/(w{3}\\.)?mprnews\\.org\\\/episode.*"]]}}],"ec":[{"1625289":{"inc":["o",["url","urlReg","(?i).*"]]}},{"2121531":{"inc":["o",["pg","eq","141375"]]}}]},pagesEval:{"pc":[141375],"ec":[1625289,2121531]},stags:{}}})(); ;;var commonWrapper=function(argument){if(!argument){argument={valuesGetter:function(){return{}},valuesSetter:function(){},verifyData:function(){return{}}}}const getVisitorUuid=function(){if(window._vwo_acc_id>=1037725){return window.VWO&&window.VWO.get("visitor.id")}else{return window.VWO._&&window.VWO._.cookies&&window.VWO._.cookies.get("_vwo_uuid")}};var pollInterval=100;var timeout=6e4;return function(){var accountIntegrationSettings={};var _interval=null;function waitForAnalyticsVariables(){try{accountIntegrationSettings=argument.valuesGetter();accountIntegrationSettings.visitorUuid=getVisitorUuid()}catch(error){accountIntegrationSettings=undefined}if(accountIntegrationSettings&&argument.verifyData(accountIntegrationSettings)){argument.valuesSetter(accountIntegrationSettings);return 1}return 0}var currentTime=0;_interval=setInterval((function(){currentTime=currentTime||performance.now();var result=waitForAnalyticsVariables();if(result||performance.now()-currentTime>=timeout){clearInterval(_interval)}}),pollInterval)}}; var pushBasedCommonWrapper=function(argument){var firedCamp={};if(!argument){argument={integrationName:"",getExperimentList:function(){},accountSettings:function(){},pushData:function(){}}}return function(){window.VWO=window.VWO||[];const getVisitorUuid=function(){if(window._vwo_acc_id>=1037725){return window.VWO&&window.VWO.get("visitor.id")}else{return window.VWO._&&window.VWO._.cookies&&window.VWO._.cookies.get("_vwo_uuid")}};var sendDebugLogsOld=function(expId,variationId,errorType,user_type,data){try{var errorPayload={f:argument["integrationName"]||"",a:window._vwo_acc_id,url:window.location.href,exp:expId,v:variationId,vwo_uuid:getVisitorUuid(),user_type:user_type};if(errorType=="initIntegrationCallback"){errorPayload["log_type"]="initIntegrationCallback";errorPayload["data"]=JSON.stringify(data||"")}else if(errorType=="timeout"){errorPayload["timeout"]=true}if(window.VWO._.customError){window.VWO._.customError({msg:"integration debug",url:window.location.href,lineno:"",colno:"",source:JSON.stringify(errorPayload)})}}catch(e){window.VWO._.customError&&window.VWO._.customError({msg:"integration debug failed",url:"",lineno:"",colno:"",source:""})}};var sendDebugLogs=function(expId,variationId,errorType,user_type){var eventName="vwo_debugLogs";var eventPayload={};try{eventPayload={intName:argument["integrationName"]||"",varId:variationId,expId:expId,type:errorType,vwo_uuid:getVisitorUuid(),user_type:user_type};if(window.VWO._.event){window.VWO._.event(eventName,eventPayload,{enableLogs:1})}}catch(e){eventPayload={msg:"integration event log failed",url:window.location.href};window.VWO._.event&&window.VWO._.event(eventName,eventPayload)}};const callbackFn=function(data){if(!data)return;var expId=data[1],variationId=data[2],repeated=data[0],singleCall=0,debug=0;var experimentList=argument.getExperimentList();var integrationName=argument["integrationName"]||"vwo";if(typeof argument.accountSettings==="function"){var accountSettings=argument.accountSettings();if(accountSettings){singleCall=accountSettings["singleCall"];debug=accountSettings["debug"]}}if(debug){sendDebugLogs(expId,variationId,"intCallTriggered",repeated)}if(singleCall&&(repeated==="vS"||repeated==="vSS")||firedCamp[expId]){return}window.expList=window.expList||{};var expList=window.expList[integrationName]=window.expList[integrationName]||[];if(expId&&variationId&&["VISUAL_AB","VISUAL","SPLIT_URL"].indexOf(_vwo_exp[expId].type)>-1){if(experimentList.indexOf(+expId)!==-1){firedCamp[expId]=variationId;var visitorUuid=getVisitorUuid();var pollInterval=100;var currentTime=0;var timeout=6e4;var user_type=_vwo_exp[expId].exec?"vwo-retry":"vwo-new";var interval=setInterval((function(){if(expList.indexOf(expId)!==-1){clearInterval(interval);return}currentTime=currentTime||performance.now();var toClearInterval=argument.pushData(expId,variationId,visitorUuid);if(debug&&toClearInterval){sendDebugLogsOld(expId,variationId,"",user_type);sendDebugLogs(expId,variationId,"intDataPushed",user_type)}var isTimeout=performance.now()-currentTime>=timeout;if(isTimeout&&debug){sendDebugLogsOld(expId,variationId,"timeout",user_type);sendDebugLogs(expId,variationId,"intTimeout",user_type)}if(toClearInterval||isTimeout){clearInterval(interval)}if(toClearInterval){window.expList[integrationName].push(expId)}}),pollInterval||100)}}};window.VWO.push(["onVariationApplied",callbackFn]);window.VWO.push(["onVariationShownSent",callbackFn])}}; var surveyDataCommonWrapper=function(argument){if(!argument){argument={getCampaignList:function(){return[]},surveyStatusChange:function(){},answerSubmitted:function(){}}}return function(){window.VWO=window.VWO||[];function getValuesFromAnswers(answers){var values=[];for(var i=0;i=timeout;if(toClearInterval||isTimeout){clearInterval(interval)}}),pollInterval)}}window.VWO.push(["onSurveyShown",function(data){commonSurveyCallback(data,argument.surveyStatusChange,"surveyShown")}]);window.VWO.push(["onSurveyCompleted",function(data){commonSurveyCallback(data,argument.surveyStatusChange,"surveyCompleted")}]);window.VWO.push(["onSurveyAnswerSubmitted",function(data){commonSurveyCallback(data,argument.answerSubmitted,"surveySubmitted")}])}}; (function(){var VWOOmniTemp={};window.VWOOmni=window.VWOOmni||{};for(var key in VWOOmniTemp)Object.prototype.hasOwnProperty.call(VWOOmniTemp,key)&&(window.VWOOmni[key]=VWOOmniTemp[key]);;})();(function(){window.VWO=window.VWO||[];var pollInterval=100;var _vis_data={};var intervalObj={};var analyticsTimerObj={};var experimentListObj={};window.VWO.push(["onVariationApplied",function(data){if(!data){return}var expId=data[1],variationId=data[2];if(expId&&variationId&&["VISUAL_AB","VISUAL","SPLIT_URL"].indexOf(window._vwo_exp[expId].type)>-1){}}])})();; ;var vD=VWO.data||{};VWO.data={content:{"fns":{"list":{"vn":1,"args":{"1":{}}}}},as:"r5.visualwebsiteoptimizer.com",dacdnUrl:"https://dev.visualwebsiteoptimizer.com",accountJSInfo:{"rp":30,"noSS":false,"pc":{"a":0,"t":0},"ts":1743322488}};for(var k in vD){VWO.data[k]=vD[k]};;var gcpfb=function(a,loadFunc,status,err,success){function vwoErr() {_vwo_err({message:"Google_Cdn failing for " + a + ". Trying Fallback..",code:"cloudcdnerr",status:status});} if(a.indexOf("/cdn/")!==-1){loadFunc(a.replace("cdn/",""),err,success); vwoErr(); return true;} else if(a.indexOf("/dcdn/")!==-1&&a.indexOf("evad.js") !== -1){loadFunc(a.replace("dcdn/",""),err,success); vwoErr(); return true;}};window.VWO=window.VWO || [];window.VWO._= window.VWO._ || {};window.VWO._.gcpfb=gcpfb;;var d={cookie:document.cookie,URL:document.URL,referrer:document.referrer};var w={VWO:{_:{}},location:{href:window.location.href,search:window.location.search},_vwoCc:window._vwoCc};;window._vwo_cdn="https://dev.visualwebsiteoptimizer.com/cdn/";window._vwo_apm_debug_cdn="https://dev.visualwebsiteoptimizer.com/cdn/";window.VWO._.useCdn=true;window.vwo_eT="br";window._VWO=window._VWO||{};window._VWO.fSeg={};window._VWO.dcdnUrl="/dcdn/settings.js";window.VWO.sTs=1743195125;window._VWO._vis_nc_lib=window._vwo_cdn+"edrv/nc-027330777ece73059cc92c6141e45cb3br.js";var loadWorker=function(url){_vwo_code.load(url, { dSC: true, onloadCb: function(xhr,a){window._vwo_wt_l=true;if(xhr.status===200 ||xhr.status===304){var code="var window="+JSON.stringify(w)+",document="+JSON.stringify(d)+";window.document=document;"+xhr.responseText;var blob=new Blob([code||"throw new Error('code not found!');"],{type:"application/javascript"}),url=URL.createObjectURL(blob);window.mainThread={webWorker:new Worker(url)};window.vwoChannelFW=new MessageChannel();window.vwoChannelToW=new MessageChannel();window.mainThread.webWorker.postMessage({vwoChannelToW:vwoChannelToW.port1,vwoChannelFW:vwoChannelFW.port2},[vwoChannelToW.port1, vwoChannelFW.port2]);if(!window._vwo_mt_f)return window._vwo_wt_f=true;_vwo_code.addScript({text:window._vwo_mt_f});delete window._vwo_mt_f}else{if(gcpfb(a,loadWorker,xhr.status)){return;}_vwo_code.finish("&e=loading_failure:"+a)}}, onerrorCb: function(a){if(gcpfb(a,loadWorker)){return;}window._vwo_wt_l=true;_vwo_code.finish("&e=loading_failure:"+a);}})};loadWorker("https://dev.visualwebsiteoptimizer.com/cdn/edrv/worker-1135852b6bc11a94eb64017a8d120ad8br.js");;var _vis_opt_file;var _vis_opt_lib;if(window.VWO._.allSettings.dataStore.previewExtraSettings!=undefined&&window.VWO._.allSettings.dataStore.previewExtraSettings.isSurveyPreviewMode){var surveyHash=window.VWO._.allSettings.dataStore.plugins.LIBINFO.SURVEY_DEBUG_EVENTS.HASH;var param1="evad.js?va=";var param2="&d=debugger_new";var param3="&sp=1&a=940895&sh="+surveyHash;_vis_opt_file=vwoCode.use_existing_jquery&&typeof vwoCode.use_existing_jquery()!=="undefined"?vwoCode.use_existing_jquery()?param1+"vanj"+param2:param1+"va_gq"+param2:param1+"edrv/va_gq-3adf809ea7b0629d1cfde6b0f4969635br.js"+param2;_vis_opt_file=_vis_opt_file+param3;_vis_opt_lib="https://dev.visualwebsiteoptimizer.com/dcdn/"+_vis_opt_file}else if(window.VWO._.allSettings.dataStore.mode!=undefined&&window.VWO._.allSettings.dataStore.mode=="PREVIEW"){ var path1 = 'edrv/pd_'; var path2 = window.VWO._.allSettings.dataStore.plugins.LIBINFO.EVAD.HASH + ".js"; ;_vis_opt_file=vwoCode.use_existing_jquery&&typeof vwoCode.use_existing_jquery()!=="undefined"?vwoCode.use_existing_jquery()?path1+"vanj"+path2:path1+"va_gq"+path2:path1+"edrv/va_gq-3adf809ea7b0629d1cfde6b0f4969635br.js"+path2;_vis_opt_lib="https://dev.visualwebsiteoptimizer.com/cdn/"+_vis_opt_file}else{_vis_opt_file=vwoCode.use_existing_jquery&&typeof vwoCode.use_existing_jquery()!=="undefined"?vwoCode.use_existing_jquery()?"edrv/vanj-7340efabe014aa7ac36a54293558de41br.js":"edrv/va_gq-3adf809ea7b0629d1cfde6b0f4969635br.js":"edrv/va_gq-3adf809ea7b0629d1cfde6b0f4969635br.js"}window._vwo_library_timer=setTimeout((function(){vwoCode.removeLoaderAndOverlay&&vwoCode.removeLoaderAndOverlay();vwoCode.finish()}),vwoCode.library_tolerance&&typeof vwoCode.library_tolerance()!=="undefined"?vwoCode.library_tolerance():2500),_vis_opt_lib=typeof _vis_opt_lib=="undefined"?window._vwo_cdn+_vis_opt_file:_vis_opt_lib;var loadLib=function(url){_vwo_code.load(url, { dSC: true, onloadCb:function(xhr,a){window._vwo_mt_l=true;if(xhr.status===200 || xhr.status===304){if(!window._vwo_wt_f)return window._vwo_mt_f=xhr.responseText;_vwo_code.addScript({text:xhr.responseText});delete window._vwo_wt_f;}else{if(gcpfb(a,loadLib,xhr.status)){return;}_vwo_code.finish("&e=loading_failure:"+a);}}, onerrorCb: function(a){if(gcpfb(a,loadLib)){return;}window._vwo_mt_l=true;_vwo_code.finish("&e=loading_failure:"+a);}})};loadLib(_vis_opt_lib);VWO.load_co=function(u,opts){return window._vwo_code.load(u,opts);};;;}}catch(e){_vwo_code.finish();_vwo_code.removeLoaderAndOverlay&&_vwo_code.removeLoaderAndOverlay();_vwo_err(e);window.VWO.caE=1}})();

Ontario declares an emergency over truck blockades in Canada

Virus Outbreak Canada Protests
Truckers and supporters block the access leading from the Ambassador Bridge, linking Detroit and Windsor, Ontario, as protests continue against COVID-19 vaccine mandates and restrictions on Friday.
Nathan Denette/The Canadian Press via AP

Canadian authorities Friday turned up the legal and public pressure on protesters to lift their blockades in Ottawa, Ontario, and at the U.S. border, with Prime Minister Justin Trudeau warning: “This unlawful activity has to end and it will end.”

Federal, provincial and local officials moved simultaneously on different fronts to break the standoff, which began with truckers and others angry over the country's COVID-19 restrictions and has morphed into a broader attack from the right on Trudeau and his Liberal government, cheered on by conservatives in the U.S.

“We heard you. It’s time to go home now," the prime minister said, warning that “everything is on the table” for ending the standoff.

Since Monday, scores of drivers mostly in pickup trucks have bottled up the Ambassador Bridge connecting Windsor, Ontario, to Detroit, disrupting the auto industry on both sides of the border. Hundreds more truckers have paralyzed downtown Ottawa over the past two weeks.

In a rapid string of developments Friday, Ontario Premier Doug Ford declared a state of emergency and threatened heavy penalties against those who interfere with the free flow of goods and people. And the mayor of Windsor asked for an injunction to put an end to the bridge protest. A judge began hearing evidence in the afternoon.

Ford said he will convene the provincial cabinet on Saturday to urgently enact measures that make it “crystal clear” it is illegal to block critical infrastructure. Violators will face up to a year in prison and a maximum fine of $100,000, he said.

“Let me be as clear as I can: There will be consequences for these actions, and they will be severe,” Ford said. “This is a pivotal, pivotal moment for our nation.”

The measures will also provide additional authority “to consider taking away the personal and commercial licenses of anyone who doesn’t comply," according to the premier's office.

Trudeau called Ontario’s decision “responsible and necessary" and said he spoke with U.S. President Joe Biden about it.

“We discussed the American and indeed global influences on the protest,” Trudeau said. “We talked about the U.S.-based flooding of the 911 phone lines in Ottawa, the presence of U.S. citizens in the blockade and the impact of foreign money to fund this illegal activity.”

He said he and Biden agreed that "for the security of people and the economy these blockades can’t continue. So make no mistake: The border cannot and will not remain closed.”

Trudeau said he understands the protesters are frustrated by the pandemic, but “these blockades are hurting everyday families, auto assembly workers, farmers, truckers, blue-collar Canadians.”

The protests have caused shortages of auto parts that have forced General Motors, Ford, Toyota and Honda to close auto plants or cancel shifts.

Federal, provincial and local authorities have hesitated to forcibly remove the self-proclaimed Freedom Convoy protesters there and elsewhere around the country, reflecting apparently a lack of manpower by local police, Canada's reverence for free speech, and fear of violence. Windsor Mayor Drew Dilkens warned earlier this week that some of the truckers are “willing to die.”

But the political pressure to reopen the bridge appeared to be mounting along with the economic toll. The Biden administration has urged Trudeau’s government to end the blockade, and Michigan's governor likewise called for a quick resolution to the standoff.

The Ambassador Bridge is the busiest U.S.-Canadian border crossing, carrying 25 percent of all trade between the two countries. The standoff comes at a time when the auto industry is already struggling to maintain production in the face of pandemic-induced shortages of computer chips and other supply-chain disruptions.

“American legislators are freaking out, and rightfully so,” said Nelson Wiseman, a political science professor at the University of Toronto. “Pressure is now being exerted by the White House on Trudeau to act more decisively.”

In addition to maintaining the bumper-to-bumper occupation of Ottawa, protesters have closed three border crossings in all: at Windsor; at Coutts, Alberta, opposite Montana; and at Emerson, Manitoba, across from North Dakota.

“We are now two weeks into the siege of Ottawa,” Ford said. “It’s an illegal occupation. It’s no longer a protest.”

The Freedom Convoy has been promoted and cheered on by many Fox News personalities and attracted support on the right from the likes of former President Donald Trump and Texas Sen. Ted Cruz.

“This is an unprecedented demonstration. It has significant levels of fundraising, coordination and communication. They have command centers established here and across the country and beyond this country,” embattled Ottawa Police Chief Peter Sloly said.

Amid signs that authorities might be prepared to get tough, police in Windsor and Ottawa awaited reinforcements from the Royal Canadian Mounted Police, the federal police force.

Ottawa’s mayor has asked for 1,800 additional police officers, which could nearly double the manpower available to the capital city's police force.

The government reaction to the protests has been marked by disagreements over who's in charge. Canada's emergency preparedness minister said this week that Ontario has ultimate responsibility, while the province's transport minister said it is the federal government’s job to secure the border.

“If anyone `takes responsibility,′ they will be charged with failure when things are not resolved quickly or if things go badly,” Wiseman said.

The protests have spread outside Canada as well. Demonstrators angry over pandemic restrictions drove toward Paris in scattered convoys of camper vans, cars and trucks Friday in an effort to blockade the French capital, despite a police ban.

And in a bulletin to local and state law enforcement officers, the U.S. Department of Homeland Security warned that truck protests may be in the works in the United States. The agency said the protests could begin in Southern California as early as this weekend and spread to Washington around the State of the Union address in March.

While the Canadian protesters are decrying vaccine mandates for truckers and other COVID-19 restrictions, many of the country’s infection measures, such as mask rules and vaccine passports for getting into restaurants and theaters, are already rapidly being lifted as the omicron surge levels off.

Trudeau has stood firm against lifting vaccine mandates. The prime minister has called protesters a “fringe” who believe in conspiracy theories and wear “tinfoil hats.” That has only incensed them further.

Pandemic restrictions have been far stricter in Canada than in the U.S., but Canadians have largely supported them. The vast majority of Canadians are vaccinated, and the COVID-19 death rate is one-third that of the United States. Canada lacks hospital capacity, so provinces have been quick to impose lockdowns when waves have hit.

Volume Button
Volume
Now Listening To Livestream
MPR News logo
On Air
BBC World Service