@automattic/newspack-blocks 4.29.0-alpha.1 → 4.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -5
- package/dist/editor.asset.php +1 -1
- package/dist/editor.js +20 -17
- package/dist/modal.asset.php +1 -1
- package/dist/modal.js +1 -1
- package/newspack-blocks.php +2 -2
- package/package.json +5 -5
- package/src/blocks/checkout-button/coupon-control.js +15 -6
- package/src/blocks/checkout-button/edit.js +30 -1
- package/src/blocks/checkout-button/view.php +32 -0
- package/src/modal-checkout/checkout-button-trigger.js +91 -6
- package/src/modal-checkout/checkout-button-trigger.test.js +143 -1
- package/src/modal-checkout/modal.js +5 -15
- package/vendor/composer/installed.php +2 -2
package/dist/modal.asset.php
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
<?php return array('dependencies' => array(), 'version' => '
|
|
1
|
+
<?php return array('dependencies' => array(), 'version' => 'a25d06a462dfabdbe12a');
|
package/dist/modal.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";function e(e,t=!1){const n=e.querySelectorAll('button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])');if(0===n.length)return!1;const o=n?.[0];let c;o.focus(),t?(document.addEventListener("keydown",function(e){if(("Tab"===e.key||9===e.keyCode)&&e.shiftKey&&document.activeElement===o){const n=t.contentWindow.document,o=n.getElementById("checkout-after-success");c=null!==o?o:n.getElementById("checkout_cancel"),c.focus(),e.preventDefault()}}),document.getElementById("newspack-a11y-last-element").addEventListener("focus",()=>{o.focus()})):(c=n[n.length-1],document.addEventListener("keydown",function(e){("Tab"===e.key||9===e.keyCode)&&(e.shiftKey?document.activeElement===o&&(c.focus(),e.preventDefault()):document.activeElement===c&&(o.focus(),e.preventDefault()))}))}const t=(e,t={})=>({...t,action:e}),n=["action","action_type","amount","currency","product_id","product_type","variation_id","variation_ids","is_variable","is_grouped","child_ids","price_summary","newspack_popup_id","prompt_title","gate_post_id","recurrence","referrer"],o=(e,t="np_modal_checkout_interaction")=>{if("function"==typeof window.gtag&&e){const o={};for(const t of n)e[t]&&("boolean"==typeof e[t]?e[t]=e[t]?"yes":"no":"true"===e[t]?e[t]="yes":"false"===e[t]&&(e[t]="no"),o[t]=e[t].toString());window.gtag("event",t,o)}},c=e=>{if("function"!=typeof window.gtag)return;let n="opened";const{amount:c="",is_variable:a="",is_grouped:r="",price:i="",variation_id:s=""}=e,l={...e};(c||i)&&(l.amount=c||i),a&&!s&&(n="opened_variations"),r&&(n="opened_grouped");const u=t(n,l);o(u)};function a(e,t=null){const n=document.createElement("input");return n.type="hidden",n.name=e,t&&(n.value=t),n}function r(e){e.requestSubmit(e.querySelector('button[type="submit"]'))}function i(e){const t="string"==typeof e?document.getElementById(e):e;if(!t)return console.warn("No container found for checkout data"),{};let n={};if("FORM"===t.tagName){const e=new FormData(t);n=Object.fromEntries(e)}const o=t.dataset.checkout;if(!o)return console.warn("No checkout data found"),n;try{n={...n,...JSON.parse(o)}}catch(e){console.warn("Error parsing checkout data")}const c=new URL(t.ownerDocument.defaultView.location.href);return c.searchParams.get("action_type")&&(n.action_type=c.searchParams.get("action_type")),n}const s=e=>{if("function"!=typeof window.gtag)return;e=e||i("newspack_modal_checkout");const n=t("dismissed",e);o(n)};function l(e){const t=e&&e.dataset?e.dataset.checkout:null;if(!t)return null;try{return JSON.parse(t)}catch(e){return null}}function u(e,t,n=null){const o=e.querySelectorAll(".wp-block-newspack-blocks-checkout-button"),c=null!=n&&""!==String(n);let a=null;return o.forEach(e=>{if(a)return;const o=e.querySelector("form"),r=l(o);r&&String(r.product_id)===String(t)&&(c&&String(r.variation_id)!==String(n)||(a=o))}),a}const d=["after_success_behavior","after_success_url","after_success_button_label","gate_post_id","newspack_popup_id","prompt_title"];const p={gate:"gate_post_id",prompt:"newspack_popup_id"};const m=newspackBlocksModal.newspack_class_prefix,_="newspack_modal_checkout_iframe",h="newspack_modal_checkout_container",w=`${m}__modal`,f="newspack-blocks__modal-variation",y=`${m}__processing-payment-text`,k=newspackBlocksModal.processing_payment_messages;let v=!1,g=newspackBlocksModal.labels.checkout_modal_title,b=null;const S=e=>{e.overlayId&&window.newspackReaderActivation?.overlays&&window.newspackReaderActivation?.overlays.remove(e.overlayId),e.setAttribute("data-state","closed"),document.body.style.overflow="auto"};window.onpageshow=e=>{e.persisted&&(document.querySelectorAll(".modal-processing").forEach(e=>e.classList.remove("modal-processing")),document.querySelectorAll(".non-modal-checkout-loading").forEach(e=>e.classList.remove("non-modal-checkout-loading")),document.querySelectorAll(`.${w}-container`).forEach(e=>S(e)))};const E=new CustomEvent("checkout-closed");var A;window.newspackRAS=window.newspackRAS||[],A=()=>{const t=document.querySelector("#newspack_modal_checkout");if(!t)return;const n=t.querySelector(`.${w}__content`),o=a("modal_checkout","1"),A=n.querySelector(`.${m}__spinner`);let q=document.querySelector(".newspack-reader__account-link")?.[0];const L="600px",R=document.createElement("iframe");R.name=_,R.style.height=L,R.style.visibility="hidden";const $=e=>{D.observe(e),"none"!==A.style.display&&(A.style.display="none"),"visible"!==R.style.visibility&&(R.style.visibility="visible"),R._ready=!0};!function(e,t,n){e._ready=!1,e._readyTimer&&clearTimeout(e._readyTimer);let o=!1,c="";function a(){o||(o=!0,clearTimeout(e._readyTimer),t.call(this))}function r(){"complete"===this.readyState&&a.call(this)}function i(){e._ready=!1,n&&n(),e._readyTimer&&clearTimeout(e._readyTimer);const t=e.contentDocument||e.contentWindow?.document;t&&(t.removeEventListener("DOMContentLoaded",a),t.removeEventListener("readystatechange",r))}function s(){if(e._ready)return void i();const t=e.contentDocument||e.contentWindow?.document;t&&0!==t.URL.indexOf("about:")?"complete"===t?.readyState?a.call(t):(t.addEventListener("DOMContentLoaded",a),t.addEventListener("readystatechange",r)):e._readyTimer=setTimeout(s,10)}e._observer||(e._observer=new MutationObserver(e=>{e.forEach(e=>{"attributes"===e.type&&"src"===e.attributeName&&(o=!1,i(),s())})}),e._observer.observe(e,{attributes:!0})),e._locationObserver||(e._locationObserver=setInterval(function(){const t=e.contentDocument||e.contentWindow?.document;t&&t.URL!==c&&(c=t.URL,o=!1,i(),s())},50)),s()}(R,function(){const n=R.contentWindow?.location;if(window.newspackReaderActivation&&n?.href?.includes("order-received")){const e=window.newspackReaderActivation,t=new Proxy(new URLSearchParams(n.search),{get:(e,t)=>e.get(t)});t.email&&(e.setReaderEmail(t.email),e.setAuthenticated(!0))}const o=R?.contentDocument?.querySelector(`#${h}`);if(!o)return;const c=i(o.querySelector("#modal-checkout-product-details")),a=document.createElement("p");a.classList.add(y);let r=[];const s=()=>{r.forEach(e=>clearTimeout(e)),r=[]},l=()=>{A.style.display="none",s(),A.querySelectorAll(`.${y}`).forEach(e=>e.remove())};!function(e,t){e.checkoutCancel?t():e.addEventListener("checkout-cancel",t)}(o,()=>{x()}),function(e,t){e.checkoutPlaceOrderStart?t():e.addEventListener("checkout-place-order-start",t)}(o,e=>{A.querySelectorAll(`.${y}`).forEach(e=>e.remove()),A.style.display="flex",s(),a.textContent=k[0]?.text??"",k.slice(1).forEach(({text:t,delay:n})=>{const o=setTimeout(()=>{e.target.dispatchEvent(new CustomEvent("checkout-place-order-processing")),a.textContent=t},n);r.push(o)}),A.appendChild(a)}),function(e,t){e.checkoutPlaceOrderError?t():e.addEventListener("checkout-place-order-error",t)}(o,l),function(e,t){e.checkoutReady?t():e.addEventListener("checkout-ready",t)}(o,()=>{if(t.initialErrors){const e=document.createElement("div");e.classList.add("woocommerce-error"),e.textContent=t.initialErrors,o.prepend(e),delete t.initialErrors}I(),N(g),R.contentWindow?.newspackBlocksModalCheckout?.checkout_nonce&&(t.checkout_nonce=R.contentWindow.newspackBlocksModalCheckout.checkout_nonce),$(o)}),function(e,t){e.checkoutComplete?t():e.addEventListener("checkout-complete",t)}(o,()=>{window.newspackRAS.push(["checkout_completed",c]),window?.newspackReaderActivation?.refreshNewslettersSignupModal&&window?.newspackReaderActivation?.getReader()?.email&&window.newspackReaderActivation.refreshNewslettersSignupModal(window.newspackReaderActivation.getReader().email),I("small"),N(newspackBlocksModal.labels.thankyou_modal_title),$(o),e(t.querySelector(`.${w}`)),l()}),function(e,t){e.checkoutPlaceOrderCriticalError?t():e.addEventListener("checkout-place-order-critical-error",t)}(o,()=>{var e;(e=b)&&(x(),A.style.display="none",t.initialErrors=newspackBlocksModal.labels.critical_error,e.requestSubmit(e.querySelector('button[type="submit"]')),l())})},()=>{A.style.display="flex"});const M=e=>new Promise((t,n)=>{const o=new URLSearchParams(e);o.append("action","modal_checkout_request"),fetch(newspackBlocksModal.ajax_url+"?"+o.toString()).then(e=>{e.ok||n(e),e.json().then(e=>{t(e.url)}).catch(n)}).catch(n)}),C=()=>"undefined"!=typeof newspack_ras_config&&!newspack_ras_config?.is_logged_in&&!window?.newspackReaderActivation?.getReader?.()?.authenticated&&newspackBlocksModal?.is_registration_required&&window?.newspackReaderActivation?.openAuthModal,B=t=>{const n=!newspackBlocksModal.has_unsupported_payment_gateway;n||t.preventDefault();const o=t.target;o.classList.add("modal-processing"),function(e){if(!e||"function"!=typeof e.querySelector)return!1;if(e.closest(".newspack-content-gate__gate"))return!1;const t=function(){let e,t;try{e=window.sessionStorage.getItem("newspack_cta_attribution")}catch(e){return null}if(!e)return null;try{t=JSON.parse(e)}catch(e){return null}return t&&1===t.v&&p[t.type]&&t.id?"number"!=typeof t.ts||Date.now()-t.ts>18e5?null:t:null}();if(!t)return!1;const n=p[t.type];if(e.querySelector(`input[name="${n}"]`))return!1;const o=document.createElement("input");o.type="hidden",o.name=n,o.value=t.id,e.prepend(o)}(o);const u=i(o);if(u.newspack_donate){const e=u.donation_frequency,t=[...o.querySelectorAll(`.donation-tier__${e}, .donation-frequency__${e}`)],n=u.donation_tier_index;let c,a;n?(c=t[n],a=u[`donation_value_${e}`]):(c=t[0],u[`donation_value_${e}_untiered`]?a=u[`donation_value_${e}_untiered`]:(a=u[`donation_value_${e}`],"other"===a&&(a=u[`donation_value_${e}_other`])));const r=i(c);for(const e in r)u[e]=r[e];u.amount=a,u.price_summary=u.summary_template.replace("{{PRICE}}",function(e,t="USD"){return parseFloat(e).toLocaleString(document.documentElement.lang,{style:"currency",currency:t,currencyDisplay:"narrowSymbol"})}(u.amount,u.currency))}u&&Object.keys(u).forEach(e=>{0===o.querySelectorAll('input[name="'+e+'"]').length&&o.prepend(a(e,u[e]))}),u.variation_id||(q=t.submitter);const d=document.querySelectorAll(`.${f}`);if(d.forEach(e=>{(C()||n)&&S(e)}),u.is_grouped||u.is_variable&&!u.variation_id){const n=[...d].find(e=>e.dataset.productId===u.product_id);if(n)return n.querySelectorAll(`form[target="${_}"]`).forEach(e=>{["after_success_behavior","after_success_url","after_success_button_label","gate_post_id","newspack_popup_id","prompt_title"].forEach(t=>{0===e.querySelectorAll('input[name="'+t+'"]').length&&e.prepend(a(t,u[t]))});const t=l(e);t&&Object.keys(t).forEach(n=>{0===e.querySelectorAll('input[name="'+n+'"]').length&&e.prepend(a(n,t[n]))})}),t.preventDefault(),o.classList.remove("modal-processing"),T(n),e(n,!1),v||c(u),void document.getElementById("newspack_modal_checkout").setAttribute("data-checkout",JSON.stringify(u))}if(n||C()){if(o.classList.remove("modal-processing"),v||c(u),v=!0,C()){t.preventDefault();const e=M(u);e.then(e=>{window.newspackReaderActivation?.setPendingCheckout?.(e)}),window.newspackReaderActivation.openAuthModal({title:newspackBlocksModal.labels.auth_modal_title,onSuccess:(t,o)=>{e.then(e=>{o?.registered&&n&&(e+=`&${newspackBlocksModal.checkout_registration_flag}=1`),n?r(P(e)):M(u).then(window.location.href=e)}).catch(e=>{console.warn("Unable to generate cart:",e),x()})},onError:()=>{x()},onDismiss:()=>{s(u),v=!1,document.getElementById("newspack_modal_checkout").removeAttribute("data-checkout")},skipSuccess:!0,skipNewslettersSignup:!0,labels:{signin:{title:newspackBlocksModal.labels.signin_modal_title},register:{title:newspackBlocksModal.labels.register_modal_title}},trigger:t.submitter,closeOnSuccess:n})}else O(),document.getElementById("newspack_modal_checkout").setAttribute("data-checkout",JSON.stringify(u));b=o}else M(u).then(e=>{window.location.href=e}),(!u.is_variable||u.variation_id)&&o.querySelectorAll("button[type=submit]:focus").forEach(e=>{e.classList.add("non-modal-checkout-loading");const t=e.innerHTML;e.innerHTML="<span>"+t+"</span>"})},P=e=>{const t=document.createElement("form");t.method="POST",t.action=e,t.target=_,t.style.display="none";const n=document.createElement("button");return n.setAttribute("type","submit"),t.appendChild(n),document.body.appendChild(t),t.addEventListener("submit",B),t},D=new ResizeObserver(e=>{if(!e||!e.length)return;if(!R.contentDocument)return;const o=e[0].contentRect;if(o){const e=.01*Math.max(document.documentElement.clientHeight,window.innerHeight||0)*90-(t.querySelector(`.${w}__header`)?.offsetHeight||0),c=o.top+o.bottom,a=Math.min(c,e);if(0===a)return void(R.style.visibility="hidden");n.style.height=a+"px",R.style.height=a+"px"}}),x=()=>{const e=R?.contentDocument?.querySelector(`#${h}`),o=e?.querySelector('input[name="after_success_url"]'),c=e?.querySelector('input[name="after_success_behavior"]'),a=document?.querySelector(".newspack-newsletters-signup-modal"),r=i(e?.querySelector("#modal-checkout-product-details"));e?.checkoutComplete||(async()=>{const e=new FormData;newspackBlocksModal.has_unsupported_payment_gateway||e.append("modal_checkout","1"),e.append("action","abandon_modal_checkout"),e.append("_wpnonce",t.checkout_nonce),t.checkout_nonce=null;try{await fetch(newspackBlocksModal.ajax_url,{method:"POST",body:e})}catch(e){console.warn("Unable to empty cart:",e)}})();const l=!(R.contentDocument&&o&&c&&e?.checkoutComplete);if((l||a)&&(A.style.display="flex",R&&n.contains(R)&&(R._ready=!1,R.src="about:blank",R.style.height=L,R.style.visibility="hidden",n.style.height=L,n.removeChild(R)),D&&D.disconnect(),document.querySelectorAll(`.${w}-container`).forEach(e=>S(e)),q&&q.focus(),document.dispatchEvent(E)),e?.checkoutComplete){const e=()=>{if(o&&c){const e=o.getAttribute("value"),t=c.getAttribute("value");if("custom"===t)window.location.href=e;else if("referrer"===t){const e=document.referrer;let t=!1;if(e)try{new URL(e).origin===window.location.origin&&(window.location.href=e,t=!0)}catch(e){}t||window.history.back()}}window?.newspackReaderActivation?.setPendingCheckout?.(),v=!1};"subscription_switch"!==r.action_type&&window?.newspackReaderActivation?.openNewslettersSignupModal?window.newspackReaderActivation.openNewslettersSignupModal({onSuccess:e,onError:e,closeOnSuccess:l}):e(),l&&(g=newspackBlocksModal.labels.checkout_modal_title,I(),N(g))}else window?.newspackReaderActivation?.setPendingCheckout?.(),s(),v=!1,document.getElementById("newspack_modal_checkout").removeAttribute("data-checkout");document.removeEventListener("keydown",U)},O=o=>{o&&(R.src=o),A.style.display="flex",T(t),n.appendChild(R),t.addEventListener("click",e=>{e.target===t&&x()}),e(t,R),document.addEventListener("keydown",U)},T=e=>{window.newspackReaderActivation?.overlays&&(e.overlayId=window.newspackReaderActivation?.overlays.add()),e.setAttribute("data-state","open"),document.body.style.overflow="hidden"},N=e=>{const n=t.querySelector(`.${w}__header h2`);n&&(n.innerText=e)},I=(e="default")=>{const n=t.querySelector(`.${w}`);n&&("small"===e?n.classList.add(`${w}--small`):n.classList.remove(`${w}--small`))};t.querySelectorAll(`.${w}__close`).forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),x()})}),document.querySelectorAll(".newspack-blocks__modal-variation").forEach(e=>{e.addEventListener("click",t=>{t.target===e&&x()}),e.querySelectorAll(`.${w}__close`).forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),x()})})});const U=e=>{"Escape"===e.key&&x()};document.querySelectorAll(".wpbnbd.wpbnbd--platform-wc, .wp-block-newspack-blocks-checkout-button, .newspack-blocks__modal-variation").forEach(e=>{e.querySelectorAll("form").forEach(e=>{newspackBlocksModal.has_unsupported_payment_gateway||e.prepend(o.cloneNode()),e.target=_,e.addEventListener("submit",B)})}),(()=>{const e=new URLSearchParams(window.location.search);if(!e.has("checkout"))return;let t=!0;const n=e.get("type");if("donate"===n){const t=e.get("layout"),n=e.get("frequency"),o=e.get("amount"),c=e.get("other");t&&n&&o&&((e,t,n,o=null)=>{let c;document.querySelectorAll(".wpbnbd.wpbnbd--platform-wc form").forEach(a=>{const r=a.querySelector(`input[name="donation_frequency"][value="${t}"]`);if(r)if("tiered"===e){const e=document.querySelector(`button[data-frequency-slug="${t}"]`);if(!e)return;e.click();const o=a.querySelector(`button[type="submit"][name="donation_value_${t}"][value="${n}"]`);if(!o)return;o.click()}else{const i="untiered"===e?a.querySelector(`input[name="donation_value_${t}_untiered"]`):a.querySelector(`input[name="donation_value_${t}"][value="${n}"]`);if(r&&i){if(r.checked=!0,"untiered"===e)i.value=n;else if("other"===n){i.click();const e=a.querySelector(`input[name="donation_value_${t}_other"]`);e&&o&&(e.value=o)}else i.checked=!0;c=a}}}),c&&r(c)})(t,n,o,c)}else if("checkout_button"===n){const n=e.get("product_id"),o=e.get("variation_id");n?t=((e,t=null)=>{const n=function(e,t,n,o={}){const{allowProductOnlyFallback:c=!1}=o;if(null==n||""===String(n))return u(e,t,null);const a=u(e,t,n);if(a)return a;const r=function(e,t,n,o={}){const{variationModalClassPrefix:c,iframeName:a}=o,r=[...e.querySelectorAll(`.${c}`)].find(e=>String(e.dataset.productId)===String(t));if(!r)return null;const i=r.querySelectorAll("form"),s=a?[...i].find(e=>e.getAttribute("target")===a):i[0];if(!s)return null;const l=[...s.querySelectorAll('input[type="radio"][name="product_id"]')].find(e=>String(e.value)===String(n));return l?(l.checked=!0,s):null}(e,t,n,o);return r?(function(e,t,n=d){if(!e||!t)return;const o=t.ownerDocument,c=new FormData(e);n.forEach(e=>{if(t.querySelector(`input[name="${e}"]`))return;const n=c.getAll(e).filter(e=>"string"==typeof e&&e);if(!n.length)return;const a=o.createElement("input");a.type="hidden",a.name=e,a.value=n[n.length-1],t.prepend(a)})}(u(e,t,null),r),r):c?u(e,t,null):null}(document,e,t,{variationModalClassPrefix:f,iframeName:_});if(n)return r(n),!0;const o=`Newspack modal checkout: no checkout form found for product_id "${e}"`+(t?` and variation_id "${t}"`:"")+". The checkout was not triggered.";return console.warn(o),!1})(n,o):(t=!1,console.warn("Newspack modal checkout: checkout_button trigger is missing product_id. The checkout was not triggered."))}else{const e=window.newspackReaderActivation?.getPendingCheckout?.();e&&r(P(e))}t&&window.history.replaceState(null,null,window.location.pathname)})(),window.newspackOpenModalCheckout=({url:e=null,title:t=null,actionType:n=null,afterSuccess:o={},onCheckoutComplete:c=null,onClose:a=null})=>{if(g=t||newspackBlocksModal.labels.checkout_modal_title,N(g),(e=new URL(e||newspackBlocksModal.checkout_url)).searchParams.has("my_account_checkout")&&e.searchParams.delete("my_account_checkout"),e.searchParams.has("modal_checkout")||e.searchParams.set("modal_checkout","1"),n&&e.searchParams.set("action_type",n),o?.url&&e.searchParams.set("after_success_url",o.url),(o?.behavior||o?.url)&&e.searchParams.set("after_success_behavior",o.behavior||"custom"),o?.buttonLabel&&e.searchParams.set("after_success_button_label",o.buttonLabel),c){const e=({detail:{action:e,data:t}})=>{"checkout_completed"===e&&c(t)};window.newspackRAS.push(t=>{t.on("activity",e);const n=()=>{t.off("activity",e),document.removeEventListener("checkout-closed",n)};document.addEventListener("checkout-closed",n)})}if(a){const e=()=>{a(),document.removeEventListener("checkout-closed",e)};document.addEventListener("checkout-closed",e)}O(e.toString())},window.newspackCloseModalCheckout=x},"undefined"!=typeof document&&("complete"!==document.readyState&&"interactive"!==document.readyState?document.addEventListener("DOMContentLoaded",A):A())})();
|
|
1
|
+
(()=>{"use strict";function e(e,t=!1){const n=e.querySelectorAll('button, [href], input:not([type="hidden"]), select, textarea, [tabindex]:not([tabindex="-1"])');if(0===n.length)return!1;const o=n?.[0];let c;o.focus(),t?(document.addEventListener("keydown",function(e){if(("Tab"===e.key||9===e.keyCode)&&e.shiftKey&&document.activeElement===o){const n=t.contentWindow.document,o=n.getElementById("checkout-after-success");c=null!==o?o:n.getElementById("checkout_cancel"),c.focus(),e.preventDefault()}}),document.getElementById("newspack-a11y-last-element").addEventListener("focus",()=>{o.focus()})):(c=n[n.length-1],document.addEventListener("keydown",function(e){("Tab"===e.key||9===e.keyCode)&&(e.shiftKey?document.activeElement===o&&(c.focus(),e.preventDefault()):document.activeElement===c&&(o.focus(),e.preventDefault()))}))}const t=(e,t={})=>({...t,action:e}),n=["action","action_type","amount","currency","product_id","product_type","variation_id","variation_ids","is_variable","is_grouped","child_ids","price_summary","newspack_popup_id","prompt_title","gate_post_id","recurrence","referrer"],o=(e,t="np_modal_checkout_interaction")=>{if("function"==typeof window.gtag&&e){const o={};for(const t of n)e[t]&&("boolean"==typeof e[t]?e[t]=e[t]?"yes":"no":"true"===e[t]?e[t]="yes":"false"===e[t]&&(e[t]="no"),o[t]=e[t].toString());window.gtag("event",t,o)}},c=e=>{if("function"!=typeof window.gtag)return;let n="opened";const{amount:c="",is_variable:a="",is_grouped:r="",price:i="",variation_id:s=""}=e,l={...e};(c||i)&&(l.amount=c||i),a&&!s&&(n="opened_variations"),r&&(n="opened_grouped");const u=t(n,l);o(u)};function a(e,t=null){const n=document.createElement("input");return n.type="hidden",n.name=e,t&&(n.value=t),n}function r(e){e.requestSubmit(e.querySelector('button[type="submit"]'))}function i(e){const t="string"==typeof e?document.getElementById(e):e;if(!t)return console.warn("No container found for checkout data"),{};let n={};if("FORM"===t.tagName){const e=new FormData(t);n=Object.fromEntries(e)}const o=t.dataset.checkout;if(!o)return console.warn("No checkout data found"),n;try{n={...n,...JSON.parse(o)}}catch(e){console.warn("Error parsing checkout data")}const c=new URL(t.ownerDocument.defaultView.location.href);return c.searchParams.get("action_type")&&(n.action_type=c.searchParams.get("action_type")),n}const s=e=>{if("function"!=typeof window.gtag)return;e=e||i("newspack_modal_checkout");const n=t("dismissed",e);o(n)};function l(e){const t=e&&e.dataset?e.dataset.checkout:null;if(!t)return null;try{return JSON.parse(t)}catch(e){return null}}function u(e,t,n=null){const o=e.querySelectorAll(".wp-block-newspack-blocks-checkout-button"),c=null!=n&&""!==String(n);let a=null;return o.forEach(e=>{if(a)return;const o=e.querySelector("form"),r=l(o);r&&String(r.product_id)===String(t)&&(c&&String(r.variation_id)!==String(n)||(a=o))}),a}const d=["after_success_behavior","after_success_url","after_success_button_label","gate_post_id","newspack_popup_id","prompt_title","coupon"];const p={gate:"gate_post_id",prompt:"newspack_popup_id"};const m=newspackBlocksModal.newspack_class_prefix,h="newspack_modal_checkout_iframe",_="newspack_modal_checkout_container",f=`${m}__modal`,w="newspack-blocks__modal-variation",y=`${m}__processing-payment-text`,k=newspackBlocksModal.processing_payment_messages;let v=!1,g=newspackBlocksModal.labels.checkout_modal_title,b=null;const S=e=>{e.overlayId&&window.newspackReaderActivation?.overlays&&window.newspackReaderActivation?.overlays.remove(e.overlayId),e.setAttribute("data-state","closed"),document.body.style.overflow="auto"};window.onpageshow=e=>{e.persisted&&(document.querySelectorAll(".modal-processing").forEach(e=>e.classList.remove("modal-processing")),document.querySelectorAll(".non-modal-checkout-loading").forEach(e=>e.classList.remove("non-modal-checkout-loading")),document.querySelectorAll(`.${f}-container`).forEach(e=>S(e)))};const E=new CustomEvent("checkout-closed");var q;window.newspackRAS=window.newspackRAS||[],q=()=>{const t=document.querySelector("#newspack_modal_checkout");if(!t)return;const n=t.querySelector(`.${f}__content`),o=a("modal_checkout","1"),q=n.querySelector(`.${m}__spinner`);let A=document.querySelector(".newspack-reader__account-link")?.[0];const L="600px",$=document.createElement("iframe");$.name=h,$.style.height=L,$.style.visibility="hidden";const R=e=>{P.observe(e),"none"!==q.style.display&&(q.style.display="none"),"visible"!==$.style.visibility&&($.style.visibility="visible"),$._ready=!0};!function(e,t,n){e._ready=!1,e._readyTimer&&clearTimeout(e._readyTimer);let o=!1,c="";function a(){o||(o=!0,clearTimeout(e._readyTimer),t.call(this))}function r(){"complete"===this.readyState&&a.call(this)}function i(){e._ready=!1,n&&n(),e._readyTimer&&clearTimeout(e._readyTimer);const t=e.contentDocument||e.contentWindow?.document;t&&(t.removeEventListener("DOMContentLoaded",a),t.removeEventListener("readystatechange",r))}function s(){if(e._ready)return void i();const t=e.contentDocument||e.contentWindow?.document;t&&0!==t.URL.indexOf("about:")?"complete"===t?.readyState?a.call(t):(t.addEventListener("DOMContentLoaded",a),t.addEventListener("readystatechange",r)):e._readyTimer=setTimeout(s,10)}e._observer||(e._observer=new MutationObserver(e=>{e.forEach(e=>{"attributes"===e.type&&"src"===e.attributeName&&(o=!1,i(),s())})}),e._observer.observe(e,{attributes:!0})),e._locationObserver||(e._locationObserver=setInterval(function(){const t=e.contentDocument||e.contentWindow?.document;t&&t.URL!==c&&(c=t.URL,o=!1,i(),s())},50)),s()}($,function(){const n=$.contentWindow?.location;if(window.newspackReaderActivation&&n?.href?.includes("order-received")){const e=window.newspackReaderActivation,t=new Proxy(new URLSearchParams(n.search),{get:(e,t)=>e.get(t)});t.email&&(e.setReaderEmail(t.email),e.setAuthenticated(!0))}const o=$?.contentDocument?.querySelector(`#${_}`);if(!o)return;const c=i(o.querySelector("#modal-checkout-product-details")),a=document.createElement("p");a.classList.add(y);let r=[];const s=()=>{r.forEach(e=>clearTimeout(e)),r=[]},l=()=>{q.style.display="none",s(),q.querySelectorAll(`.${y}`).forEach(e=>e.remove())};!function(e,t){e.checkoutCancel?t():e.addEventListener("checkout-cancel",t)}(o,()=>{x()}),function(e,t){e.checkoutPlaceOrderStart?t():e.addEventListener("checkout-place-order-start",t)}(o,e=>{q.querySelectorAll(`.${y}`).forEach(e=>e.remove()),q.style.display="flex",s(),a.textContent=k[0]?.text??"",k.slice(1).forEach(({text:t,delay:n})=>{const o=setTimeout(()=>{e.target.dispatchEvent(new CustomEvent("checkout-place-order-processing")),a.textContent=t},n);r.push(o)}),q.appendChild(a)}),function(e,t){e.checkoutPlaceOrderError?t():e.addEventListener("checkout-place-order-error",t)}(o,l),function(e,t){e.checkoutReady?t():e.addEventListener("checkout-ready",t)}(o,()=>{if(t.initialErrors){const e=document.createElement("div");e.classList.add("woocommerce-error"),e.textContent=t.initialErrors,o.prepend(e),delete t.initialErrors}I(),N(g),$.contentWindow?.newspackBlocksModalCheckout?.checkout_nonce&&(t.checkout_nonce=$.contentWindow.newspackBlocksModalCheckout.checkout_nonce),R(o)}),function(e,t){e.checkoutComplete?t():e.addEventListener("checkout-complete",t)}(o,()=>{window.newspackRAS.push(["checkout_completed",c]),window?.newspackReaderActivation?.refreshNewslettersSignupModal&&window?.newspackReaderActivation?.getReader()?.email&&window.newspackReaderActivation.refreshNewslettersSignupModal(window.newspackReaderActivation.getReader().email),I("small"),N(newspackBlocksModal.labels.thankyou_modal_title),R(o),e(t.querySelector(`.${f}`)),l()}),function(e,t){e.checkoutPlaceOrderCriticalError?t():e.addEventListener("checkout-place-order-critical-error",t)}(o,()=>{var e;(e=b)&&(x(),q.style.display="none",t.initialErrors=newspackBlocksModal.labels.critical_error,e.requestSubmit(e.querySelector('button[type="submit"]')),l())})},()=>{q.style.display="flex"});const M=e=>new Promise((t,n)=>{const o=new URLSearchParams(e);o.append("action","modal_checkout_request"),fetch(newspackBlocksModal.ajax_url+"?"+o.toString()).then(e=>{e.ok||n(e),e.json().then(e=>{t(e.url)}).catch(n)}).catch(n)}),C=()=>"undefined"!=typeof newspack_ras_config&&!newspack_ras_config?.is_logged_in&&!window?.newspackReaderActivation?.getReader?.()?.authenticated&&newspackBlocksModal?.is_registration_required&&window?.newspackReaderActivation?.openAuthModal,B=t=>{const n=!newspackBlocksModal.has_unsupported_payment_gateway;n||t.preventDefault();const o=t.target;o.classList.add("modal-processing"),function(e){if(!e||"function"!=typeof e.querySelector)return!1;if(e.closest(".newspack-content-gate__gate"))return!1;const t=function(){let e,t;try{e=window.sessionStorage.getItem("newspack_cta_attribution")}catch(e){return null}if(!e)return null;try{t=JSON.parse(e)}catch(e){return null}return t&&1===t.v&&p[t.type]&&t.id?"number"!=typeof t.ts||Date.now()-t.ts>18e5?null:t:null}();if(!t)return!1;const n=p[t.type];if(e.querySelector(`input[name="${n}"]`))return!1;const o=document.createElement("input");o.type="hidden",o.name=n,o.value=t.id,e.prepend(o)}(o);const u=i(o);if(u.newspack_donate){const e=u.donation_frequency,t=[...o.querySelectorAll(`.donation-tier__${e}, .donation-frequency__${e}`)],n=u.donation_tier_index;let c,a;n?(c=t[n],a=u[`donation_value_${e}`]):(c=t[0],u[`donation_value_${e}_untiered`]?a=u[`donation_value_${e}_untiered`]:(a=u[`donation_value_${e}`],"other"===a&&(a=u[`donation_value_${e}_other`])));const r=i(c);for(const e in r)u[e]=r[e];u.amount=a,u.price_summary=u.summary_template.replace("{{PRICE}}",function(e,t="USD"){return parseFloat(e).toLocaleString(document.documentElement.lang,{style:"currency",currency:t,currencyDisplay:"narrowSymbol"})}(u.amount,u.currency))}u&&Object.keys(u).forEach(e=>{0===o.querySelectorAll('input[name="'+e+'"]').length&&o.prepend(a(e,u[e]))}),u.variation_id||(A=t.submitter);const m=document.querySelectorAll(`.${w}`);if(m.forEach(e=>{(C()||n)&&S(e)}),u.is_grouped||u.is_variable&&!u.variation_id){const n=[...m].find(e=>e.dataset.productId===u.product_id);if(n)return n.querySelectorAll(`form[target="${h}"]`).forEach(e=>{!function(e,t,n=d){if(!e||!t)return;const o=e.ownerDocument;n.forEach(n=>{e.querySelectorAll(`input[name="${n}"]`).forEach(e=>e.remove());const c=t[n],a=null==c?"":String(c);if(!a)return;const r=o.createElement("input");r.type="hidden",r.name=n,r.value=a,e.prepend(r)})}(e,u);const t=l(e);t&&Object.keys(t).forEach(n=>{0===e.querySelectorAll('input[name="'+n+'"]').length&&e.prepend(a(n,t[n]))})}),t.preventDefault(),o.classList.remove("modal-processing"),T(n),e(n,!1),v||c(u),void document.getElementById("newspack_modal_checkout").setAttribute("data-checkout",JSON.stringify(u))}if(n||C()){if(o.classList.remove("modal-processing"),v||c(u),v=!0,C()){t.preventDefault();const e=M(u);e.then(e=>{window.newspackReaderActivation?.setPendingCheckout?.(e)}),window.newspackReaderActivation.openAuthModal({title:newspackBlocksModal.labels.auth_modal_title,onSuccess:(t,o)=>{e.then(e=>{o?.registered&&n&&(e+=`&${newspackBlocksModal.checkout_registration_flag}=1`),n?r(D(e)):M(u).then(window.location.href=e)}).catch(e=>{console.warn("Unable to generate cart:",e),x()})},onError:()=>{x()},onDismiss:()=>{s(u),v=!1,document.getElementById("newspack_modal_checkout").removeAttribute("data-checkout")},skipSuccess:!0,skipNewslettersSignup:!0,labels:{signin:{title:newspackBlocksModal.labels.signin_modal_title},register:{title:newspackBlocksModal.labels.register_modal_title}},trigger:t.submitter,closeOnSuccess:n})}else O(),document.getElementById("newspack_modal_checkout").setAttribute("data-checkout",JSON.stringify(u));b=o}else M(u).then(e=>{window.location.href=e}),(!u.is_variable||u.variation_id)&&o.querySelectorAll("button[type=submit]:focus").forEach(e=>{e.classList.add("non-modal-checkout-loading");const t=e.innerHTML;e.innerHTML="<span>"+t+"</span>"})},D=e=>{const t=document.createElement("form");t.method="POST",t.action=e,t.target=h,t.style.display="none";const n=document.createElement("button");return n.setAttribute("type","submit"),t.appendChild(n),document.body.appendChild(t),t.addEventListener("submit",B),t},P=new ResizeObserver(e=>{if(!e||!e.length)return;if(!$.contentDocument)return;const o=e[0].contentRect;if(o){const e=.01*Math.max(document.documentElement.clientHeight,window.innerHeight||0)*90-(t.querySelector(`.${f}__header`)?.offsetHeight||0),c=o.top+o.bottom,a=Math.min(c,e);if(0===a)return void($.style.visibility="hidden");n.style.height=a+"px",$.style.height=a+"px"}}),x=()=>{const e=$?.contentDocument?.querySelector(`#${_}`),o=e?.querySelector('input[name="after_success_url"]'),c=e?.querySelector('input[name="after_success_behavior"]'),a=document?.querySelector(".newspack-newsletters-signup-modal"),r=i(e?.querySelector("#modal-checkout-product-details"));e?.checkoutComplete||(async()=>{const e=new FormData;newspackBlocksModal.has_unsupported_payment_gateway||e.append("modal_checkout","1"),e.append("action","abandon_modal_checkout"),e.append("_wpnonce",t.checkout_nonce),t.checkout_nonce=null;try{await fetch(newspackBlocksModal.ajax_url,{method:"POST",body:e})}catch(e){console.warn("Unable to empty cart:",e)}})();const l=!($.contentDocument&&o&&c&&e?.checkoutComplete);if((l||a)&&(q.style.display="flex",$&&n.contains($)&&($._ready=!1,$.src="about:blank",$.style.height=L,$.style.visibility="hidden",n.style.height=L,n.removeChild($)),P&&P.disconnect(),document.querySelectorAll(`.${f}-container`).forEach(e=>S(e)),A&&A.focus(),document.dispatchEvent(E)),e?.checkoutComplete){const e=()=>{if(o&&c){const e=o.getAttribute("value"),t=c.getAttribute("value");if("custom"===t)window.location.href=e;else if("referrer"===t){const e=document.referrer;let t=!1;if(e)try{new URL(e).origin===window.location.origin&&(window.location.href=e,t=!0)}catch(e){}t||window.history.back()}}window?.newspackReaderActivation?.setPendingCheckout?.(),v=!1};"subscription_switch"!==r.action_type&&window?.newspackReaderActivation?.openNewslettersSignupModal?window.newspackReaderActivation.openNewslettersSignupModal({onSuccess:e,onError:e,closeOnSuccess:l}):e(),l&&(g=newspackBlocksModal.labels.checkout_modal_title,I(),N(g))}else window?.newspackReaderActivation?.setPendingCheckout?.(),s(),v=!1,document.getElementById("newspack_modal_checkout").removeAttribute("data-checkout");document.removeEventListener("keydown",U)},O=o=>{o&&($.src=o),q.style.display="flex",T(t),n.appendChild($),t.addEventListener("click",e=>{e.target===t&&x()}),e(t,$),document.addEventListener("keydown",U)},T=e=>{window.newspackReaderActivation?.overlays&&(e.overlayId=window.newspackReaderActivation?.overlays.add()),e.setAttribute("data-state","open"),document.body.style.overflow="hidden"},N=e=>{const n=t.querySelector(`.${f}__header h2`);n&&(n.innerText=e)},I=(e="default")=>{const n=t.querySelector(`.${f}`);n&&("small"===e?n.classList.add(`${f}--small`):n.classList.remove(`${f}--small`))};t.querySelectorAll(`.${f}__close`).forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),x()})}),document.querySelectorAll(".newspack-blocks__modal-variation").forEach(e=>{e.addEventListener("click",t=>{t.target===e&&x()}),e.querySelectorAll(`.${f}__close`).forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),x()})})});const U=e=>{"Escape"===e.key&&x()};document.querySelectorAll(".wpbnbd.wpbnbd--platform-wc, .wp-block-newspack-blocks-checkout-button, .newspack-blocks__modal-variation").forEach(e=>{e.querySelectorAll("form").forEach(e=>{newspackBlocksModal.has_unsupported_payment_gateway||e.prepend(o.cloneNode()),e.target=h,e.addEventListener("submit",B)})}),(()=>{const e=new URLSearchParams(window.location.search);if(!e.has("checkout"))return;let t=!0;const n=e.get("type");if("donate"===n){const t=e.get("layout"),n=e.get("frequency"),o=e.get("amount"),c=e.get("other");t&&n&&o&&((e,t,n,o=null)=>{let c;document.querySelectorAll(".wpbnbd.wpbnbd--platform-wc form").forEach(a=>{const r=a.querySelector(`input[name="donation_frequency"][value="${t}"]`);if(r)if("tiered"===e){const e=document.querySelector(`button[data-frequency-slug="${t}"]`);if(!e)return;e.click();const o=a.querySelector(`button[type="submit"][name="donation_value_${t}"][value="${n}"]`);if(!o)return;o.click()}else{const i="untiered"===e?a.querySelector(`input[name="donation_value_${t}_untiered"]`):a.querySelector(`input[name="donation_value_${t}"][value="${n}"]`);if(r&&i){if(r.checked=!0,"untiered"===e)i.value=n;else if("other"===n){i.click();const e=a.querySelector(`input[name="donation_value_${t}_other"]`);e&&o&&(e.value=o)}else i.checked=!0;c=a}}}),c&&r(c)})(t,n,o,c)}else if("checkout_button"===n){const n=e.get("product_id"),o=e.get("variation_id");n?t=((e,t=null)=>{const n=function(e,t,n,o={}){const{allowProductOnlyFallback:c=!1}=o;if(null==n||""===String(n))return u(e,t,null);const a=u(e,t,n);if(a)return a;const r=function(e,t,n,o={}){const{variationModalClassPrefix:c,iframeName:a}=o,r=[...e.querySelectorAll(`.${c}`)].find(e=>String(e.dataset.productId)===String(t));if(!r)return null;const i=r.querySelectorAll("form"),s=a?[...i].find(e=>e.getAttribute("target")===a):i[0];if(!s)return null;const l=[...s.querySelectorAll('input[type="radio"][name="product_id"]')].find(e=>String(e.value)===String(n));return l?(l.checked=!0,s):null}(e,t,n,o);return r?(function(e,t,n=d){if(!e||!t)return;const o=t.ownerDocument,c=new FormData(e);n.forEach(e=>{if(t.querySelector(`input[name="${e}"]`))return;const n=c.getAll(e).filter(e=>"string"==typeof e&&e);if(!n.length)return;const a=o.createElement("input");a.type="hidden",a.name=e,a.value=n[n.length-1],t.prepend(a)})}(function(e,t){const n=e.querySelectorAll(".wp-block-newspack-blocks-checkout-button");let o=null,c=null;return n.forEach(e=>{if(c)return;const n=e.querySelector("form"),a=l(n);a&&String(a.product_id)===String(t)&&(a.variation_id?o=o||n:c=n)}),c||o}(e,t),r),r):c?u(e,t,null):null}(document,e,t,{variationModalClassPrefix:w,iframeName:h});if(n)return r(n),!0;const o=`Newspack modal checkout: no checkout form found for product_id "${e}"`+(t?` and variation_id "${t}"`:"")+". The checkout was not triggered.";return console.warn(o),!1})(n,o):(t=!1,console.warn("Newspack modal checkout: checkout_button trigger is missing product_id. The checkout was not triggered."))}else{const e=window.newspackReaderActivation?.getPendingCheckout?.();e&&r(D(e))}t&&window.history.replaceState(null,null,window.location.pathname)})(),window.newspackOpenModalCheckout=({url:e=null,title:t=null,actionType:n=null,afterSuccess:o={},onCheckoutComplete:c=null,onClose:a=null})=>{if(g=t||newspackBlocksModal.labels.checkout_modal_title,N(g),(e=new URL(e||newspackBlocksModal.checkout_url)).searchParams.has("my_account_checkout")&&e.searchParams.delete("my_account_checkout"),e.searchParams.has("modal_checkout")||e.searchParams.set("modal_checkout","1"),n&&e.searchParams.set("action_type",n),o?.url&&e.searchParams.set("after_success_url",o.url),(o?.behavior||o?.url)&&e.searchParams.set("after_success_behavior",o.behavior||"custom"),o?.buttonLabel&&e.searchParams.set("after_success_button_label",o.buttonLabel),c){const e=({detail:{action:e,data:t}})=>{"checkout_completed"===e&&c(t)};window.newspackRAS.push(t=>{t.on("activity",e);const n=()=>{t.off("activity",e),document.removeEventListener("checkout-closed",n)};document.addEventListener("checkout-closed",n)})}if(a){const e=()=>{a(),document.removeEventListener("checkout-closed",e)};document.addEventListener("checkout-closed",e)}O(e.toString())},window.newspackCloseModalCheckout=x},"undefined"!=typeof document&&("complete"!==document.readyState&&"interactive"!==document.readyState?document.addEventListener("DOMContentLoaded",q):q())})();
|
package/newspack-blocks.php
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Author URI: https://newspack.com/
|
|
8
8
|
* Text Domain: newspack-blocks
|
|
9
9
|
* Domain Path: /languages
|
|
10
|
-
* Version: 4.29.0
|
|
10
|
+
* Version: 4.29.0
|
|
11
11
|
*
|
|
12
12
|
* @package Newspack_Blocks
|
|
13
13
|
*/
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ );
|
|
16
16
|
define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' );
|
|
17
17
|
define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) );
|
|
18
|
-
define( 'NEWSPACK_BLOCKS__VERSION', '4.29.0
|
|
18
|
+
define( 'NEWSPACK_BLOCKS__VERSION', '4.29.0' );
|
|
19
19
|
|
|
20
20
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php';
|
|
21
21
|
require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automattic/newspack-blocks",
|
|
3
|
-
"version": "4.29.0
|
|
3
|
+
"version": "4.29.0",
|
|
4
4
|
"author": "Automattic",
|
|
5
5
|
"description": "=== Newspack Blocks === Contributors: (this should be a list of wordpress.org userid's) Donate link: https://example.com/ Tags: comments, spam Requires at least: 4.5 Tested up to: 5.1.1 Stable tag: 0.1.0 License: GPLv2 or later License URI: https://www.gnu.org/licenses/gpl-2.0.html",
|
|
6
6
|
"repository": {
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"classnames": "^2.5.1",
|
|
48
48
|
"lodash": "^4.17.21",
|
|
49
|
-
"newspack-colors": "1.1.1
|
|
50
|
-
"newspack-icons": "1.1.0
|
|
49
|
+
"newspack-colors": "1.1.1",
|
|
50
|
+
"newspack-icons": "1.1.0",
|
|
51
51
|
"redux": "^5.0.0",
|
|
52
52
|
"redux-saga": "^1.5.0",
|
|
53
53
|
"regenerator-runtime": "^0.14.1",
|
|
@@ -55,8 +55,8 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/lodash": "^4.17.23",
|
|
58
|
-
"newspack-components": "4.6.0
|
|
59
|
-
"newspack-scripts": "5.10.0
|
|
58
|
+
"newspack-components": "4.6.0",
|
|
59
|
+
"newspack-scripts": "5.10.0"
|
|
60
60
|
},
|
|
61
61
|
"overrides": {
|
|
62
62
|
"path-to-regexp": "1.7.0"
|
|
@@ -20,9 +20,11 @@ import apiFetch from '@wordpress/api-fetch';
|
|
|
20
20
|
* @param {Object} props
|
|
21
21
|
* @param {string} props.value Currently selected coupon code.
|
|
22
22
|
* @param {Function} props.onChange Called with the selected coupon code (or '').
|
|
23
|
+
* @param {boolean} props.disabled Whether a coupon can be set. A stored code stays
|
|
24
|
+
* visible and removable so it can't get stranded.
|
|
23
25
|
* @return {JSX.Element} The control.
|
|
24
26
|
*/
|
|
25
|
-
export default function CouponControl( { value, onChange } ) {
|
|
27
|
+
export default function CouponControl( { value, onChange, disabled = false } ) {
|
|
26
28
|
const [ inFlight, setInFlight ] = useState( false );
|
|
27
29
|
const [ suggestions, setSuggestions ] = useState( [] );
|
|
28
30
|
const [ selected, setSelected ] = useState( false );
|
|
@@ -100,9 +102,13 @@ export default function CouponControl( { value, onChange } ) {
|
|
|
100
102
|
<div className="newspack-checkout-button__coupon-field">
|
|
101
103
|
<BaseControl label={ __( 'Coupon', 'newspack-blocks' ) } id="newspack-checkout-button-coupon">
|
|
102
104
|
<TextControl value={ selected } __next40pxDefaultSize disabled />
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
105
|
+
{ ! disabled && (
|
|
106
|
+
<>
|
|
107
|
+
<Button variant="link" onClick={ () => setIsChanging( true ) }>
|
|
108
|
+
{ __( 'Edit', 'newspack-blocks' ) }
|
|
109
|
+
</Button>{ ' ' }
|
|
110
|
+
</>
|
|
111
|
+
) }
|
|
106
112
|
<Button
|
|
107
113
|
variant="link"
|
|
108
114
|
isDestructive
|
|
@@ -121,13 +127,16 @@ export default function CouponControl( { value, onChange } ) {
|
|
|
121
127
|
return (
|
|
122
128
|
<div className="newspack-checkout-button__coupon-field">
|
|
123
129
|
<FormTokenField
|
|
124
|
-
placeholder={
|
|
130
|
+
placeholder={
|
|
131
|
+
disabled ? __( 'Coupons are not available', 'newspack-blocks' ) : __( 'Type to search for a coupon…', 'newspack-blocks' )
|
|
132
|
+
}
|
|
125
133
|
label={ __( 'Coupon', 'newspack-blocks' ) }
|
|
126
134
|
maxLength={ 1 }
|
|
127
135
|
value={ [] }
|
|
128
136
|
onChange={ onTokenChange }
|
|
129
137
|
onInputChange={ handleInputChange }
|
|
130
|
-
suggestions={ suggestions }
|
|
138
|
+
suggestions={ disabled ? [] : suggestions }
|
|
139
|
+
disabled={ disabled }
|
|
131
140
|
__next40pxDefaultSize
|
|
132
141
|
/>
|
|
133
142
|
{ inFlight && <Spinner /> }
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
SelectControl,
|
|
28
28
|
FormTokenField,
|
|
29
29
|
Button,
|
|
30
|
+
Notice,
|
|
30
31
|
Spinner,
|
|
31
32
|
// eslint-disable-next-line @wordpress/no-unsafe-wp-apis
|
|
32
33
|
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
@@ -138,6 +139,10 @@ function ProductControl( props ) {
|
|
|
138
139
|
fetchSaved();
|
|
139
140
|
} else {
|
|
140
141
|
setSelected( false );
|
|
142
|
+
// Clear the parent's copy too, otherwise product-derived state (e.g.
|
|
143
|
+
// whether this is a donation) keeps describing the product that was
|
|
144
|
+
// just removed.
|
|
145
|
+
props.onProduct( {} );
|
|
141
146
|
}
|
|
142
147
|
}, [ props.value ] );
|
|
143
148
|
function onChange( tokens ) {
|
|
@@ -208,6 +213,11 @@ function CheckoutButtonEdit( props ) {
|
|
|
208
213
|
const [ variations, setVariations ] = useState( [] );
|
|
209
214
|
const [ nyp, setNYP ] = useState( false );
|
|
210
215
|
|
|
216
|
+
// Resolved server-side, since a donation is not always identifiable from the
|
|
217
|
+
// product meta. Variations inherit it from their parent, which is the product
|
|
218
|
+
// fetched here, so the selected variation needs no separate check.
|
|
219
|
+
const isDonation = !! productData?.newspack_is_donation;
|
|
220
|
+
|
|
211
221
|
function handleProduct( data ) {
|
|
212
222
|
setProductData( data );
|
|
213
223
|
// Handle product variation data.
|
|
@@ -339,7 +349,26 @@ function CheckoutButtonEdit( props ) {
|
|
|
339
349
|
) }
|
|
340
350
|
</ProductControl>
|
|
341
351
|
{ newspack_blocks_data?.coupons_enabled && (
|
|
342
|
-
|
|
352
|
+
<>
|
|
353
|
+
{ /*
|
|
354
|
+
* Coupons are not supported on donation products. The control is
|
|
355
|
+
* disabled rather than hidden so a code stored before the product
|
|
356
|
+
* was swapped stays visible — and removable, since the block emits
|
|
357
|
+
* it regardless of donation status.
|
|
358
|
+
*/ }
|
|
359
|
+
{ isDonation && (
|
|
360
|
+
<Notice status={ coupon ? 'warning' : 'info' } isDismissible={ false }>
|
|
361
|
+
{ coupon
|
|
362
|
+
? sprintf(
|
|
363
|
+
// translators: %s: the coupon code stored on the block.
|
|
364
|
+
__( 'Donation products do not support coupons. "%s" will not be applied.', 'newspack-blocks' ),
|
|
365
|
+
coupon
|
|
366
|
+
)
|
|
367
|
+
: __( 'Donation products do not support coupons.', 'newspack-blocks' ) }
|
|
368
|
+
</Notice>
|
|
369
|
+
) }
|
|
370
|
+
<CouponControl value={ coupon } onChange={ value => setAttributes( { coupon: value } ) } disabled={ isDonation } />
|
|
371
|
+
</>
|
|
343
372
|
) }
|
|
344
373
|
<WidthControl selectedWidth={ width } setAttributes={ setAttributes } />
|
|
345
374
|
</PanelBody>
|
|
@@ -24,6 +24,38 @@ function register_block() {
|
|
|
24
24
|
}
|
|
25
25
|
add_action( 'init', __NAMESPACE__ . '\\register_block' );
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Expose whether a product is a donation to the products REST response.
|
|
29
|
+
*
|
|
30
|
+
* The block editor needs this to tell the publisher that an attached coupon
|
|
31
|
+
* will not be applied: Newspack disables coupons for any cart containing a
|
|
32
|
+
* donation (see Newspack\Donations::disable_coupons()). It cannot be derived
|
|
33
|
+
* from the product meta alone, because the legacy donation product and its
|
|
34
|
+
* children are matched by ID rather than by the donation flag, so the answer
|
|
35
|
+
* is delegated to Donations::is_donation_product().
|
|
36
|
+
*/
|
|
37
|
+
function register_donation_rest_field() {
|
|
38
|
+
if ( ! class_exists( '\Newspack\Donations' ) || ! method_exists( '\Newspack\Donations', 'is_donation_product' ) ) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
register_rest_field(
|
|
42
|
+
'product',
|
|
43
|
+
'newspack_is_donation',
|
|
44
|
+
[
|
|
45
|
+
'get_callback' => function ( $product ) {
|
|
46
|
+
return (bool) \Newspack\Donations::is_donation_product( $product['id'] );
|
|
47
|
+
},
|
|
48
|
+
'schema' => [
|
|
49
|
+
'description' => __( 'Whether the product is treated as a donation by Newspack.', 'newspack-blocks' ),
|
|
50
|
+
'type' => 'boolean',
|
|
51
|
+
'context' => [ 'view', 'edit' ],
|
|
52
|
+
'readonly' => true,
|
|
53
|
+
],
|
|
54
|
+
]
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
add_action( 'rest_api_init', __NAMESPACE__ . '\\register_donation_rest_field' );
|
|
58
|
+
|
|
27
59
|
/**
|
|
28
60
|
* Render the block.
|
|
29
61
|
*
|
|
@@ -58,6 +58,41 @@ export function findCheckoutButtonForm( root, productId, variationId = null ) {
|
|
|
58
58
|
return match;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Find the button whose context a picker submission should inherit.
|
|
63
|
+
*
|
|
64
|
+
* Prefers a button that is not locked to a single variation: it stands for the
|
|
65
|
+
* whole product, so its context — including any attached coupon — applies to
|
|
66
|
+
* whichever variation the reader picks. A locked button was configured for one
|
|
67
|
+
* specific variation and is only used when nothing better exists.
|
|
68
|
+
*
|
|
69
|
+
* @param {Document|HTMLElement} root The DOM root to search.
|
|
70
|
+
* @param {string} productId The requested product ID.
|
|
71
|
+
*
|
|
72
|
+
* @return {HTMLFormElement|null} The donor form, or null.
|
|
73
|
+
*/
|
|
74
|
+
function findContextDonorForm( root, productId ) {
|
|
75
|
+
const buttons = root.querySelectorAll( '.wp-block-newspack-blocks-checkout-button' );
|
|
76
|
+
let fallback = null;
|
|
77
|
+
let unlocked = null;
|
|
78
|
+
buttons.forEach( button => {
|
|
79
|
+
if ( unlocked ) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const form = button.querySelector( 'form' );
|
|
83
|
+
const data = readCheckoutData( form );
|
|
84
|
+
if ( ! data || String( data.product_id ) !== String( productId ) ) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if ( ! data.variation_id ) {
|
|
88
|
+
unlocked = form;
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
fallback = fallback || form;
|
|
92
|
+
} );
|
|
93
|
+
return unlocked || fallback;
|
|
94
|
+
}
|
|
95
|
+
|
|
61
96
|
/**
|
|
62
97
|
* Select the requested variation in a product picker.
|
|
63
98
|
* Picker forms use the selected radio value instead of `data-checkout`.
|
|
@@ -98,6 +133,12 @@ export function selectPickerForm( root, productId, variationId, options = {} ) {
|
|
|
98
133
|
/**
|
|
99
134
|
* Hidden fields copied from a source checkout button to a picker submission.
|
|
100
135
|
*
|
|
136
|
+
* The picker form is rendered once per variable product in the footer and is
|
|
137
|
+
* submitted instead of the button's own form, so anything the block attached to
|
|
138
|
+
* that button — after-success behavior, attribution, the auto-applied coupon —
|
|
139
|
+
* is lost unless it is listed here. Shared with modal.js so the click path and
|
|
140
|
+
* the URL-trigger path carry the same context.
|
|
141
|
+
*
|
|
101
142
|
* @type {string[]}
|
|
102
143
|
*/
|
|
103
144
|
export const PICKER_CONTEXT_FIELDS = [
|
|
@@ -107,12 +148,54 @@ export const PICKER_CONTEXT_FIELDS = [
|
|
|
107
148
|
'gate_post_id',
|
|
108
149
|
'newspack_popup_id',
|
|
109
150
|
'prompt_title',
|
|
151
|
+
'coupon',
|
|
110
152
|
];
|
|
111
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Stamp context fields onto a picker form from the button that opened it.
|
|
156
|
+
*
|
|
157
|
+
* Authoritative, unlike copyContextFields(): the picker is rendered once per
|
|
158
|
+
* parent product and shared by every button targeting it, and nothing clears it
|
|
159
|
+
* when the modal closes, so each open must overwrite whatever the previous one
|
|
160
|
+
* left behind. An absent value removes the field rather than preserving a stale
|
|
161
|
+
* one — for `coupon` that is the difference between the reader's discount and
|
|
162
|
+
* a discount attached to a different button.
|
|
163
|
+
*
|
|
164
|
+
* @param {HTMLFormElement|null} targetForm Picker form to stamp.
|
|
165
|
+
* @param {Object|null} data Checkout data read from the clicked button's form.
|
|
166
|
+
* @param {string[]} fields Field names to stamp.
|
|
167
|
+
*
|
|
168
|
+
* @return {void}
|
|
169
|
+
*/
|
|
170
|
+
export function applyContextFields( targetForm, data, fields = PICKER_CONTEXT_FIELDS ) {
|
|
171
|
+
if ( ! targetForm || ! data ) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const doc = targetForm.ownerDocument;
|
|
175
|
+
fields.forEach( name => {
|
|
176
|
+
// Drop whatever a previous open left behind before writing this one's value.
|
|
177
|
+
targetForm.querySelectorAll( `input[name="${ name }"]` ).forEach( input => input.remove() );
|
|
178
|
+
const raw = data[ name ];
|
|
179
|
+
const value = raw === undefined || raw === null ? '' : String( raw );
|
|
180
|
+
if ( ! value ) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const input = doc.createElement( 'input' );
|
|
184
|
+
input.type = 'hidden';
|
|
185
|
+
input.name = name;
|
|
186
|
+
input.value = value;
|
|
187
|
+
targetForm.prepend( input );
|
|
188
|
+
} );
|
|
189
|
+
}
|
|
190
|
+
|
|
112
191
|
/**
|
|
113
192
|
* Copy context fields. Target values are preserved, empty source values are
|
|
114
193
|
* skipped, and null forms are ignored.
|
|
115
194
|
*
|
|
195
|
+
* Used by the URL-trigger path, which runs once on load before any click. The
|
|
196
|
+
* click path uses applyContextFields() instead and overwrites anything left
|
|
197
|
+
* here, so preserving existing values cannot strand a stale coupon.
|
|
198
|
+
*
|
|
116
199
|
* @param {HTMLFormElement|null} sourceForm Checkout button form to read from.
|
|
117
200
|
* @param {HTMLFormElement|null} targetForm Picker form to copy into.
|
|
118
201
|
* @param {string[]} fields Field names to copy.
|
|
@@ -173,12 +256,14 @@ export function resolveCheckoutButtonForm( root, productId, variationId, options
|
|
|
173
256
|
|
|
174
257
|
const picker = selectPickerForm( root, productId, variationId, options );
|
|
175
258
|
if ( picker ) {
|
|
176
|
-
// The
|
|
177
|
-
//
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
|
|
259
|
+
// The picker is only reached because no button matches the requested
|
|
260
|
+
// variation, so the context has to come from some other button for this
|
|
261
|
+
// product. Since PICKER_CONTEXT_FIELDS now carries `coupon`, that choice
|
|
262
|
+
// decides a discount: a button locked to a variation was configured for
|
|
263
|
+
// that variation, so its coupon should not follow the reader to a
|
|
264
|
+
// different one. Prefer an unlocked button, which stands for the whole
|
|
265
|
+
// product, and fall back to DOM order only when there isn't one.
|
|
266
|
+
copyContextFields( findContextDonorForm( root, productId ), picker );
|
|
182
267
|
return picker;
|
|
183
268
|
}
|
|
184
269
|
|
|
@@ -2,7 +2,15 @@
|
|
|
2
2
|
* Tests for the checkout-button URL trigger resolution helpers.
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
readCheckoutData,
|
|
7
|
+
findCheckoutButtonForm,
|
|
8
|
+
selectPickerForm,
|
|
9
|
+
resolveCheckoutButtonForm,
|
|
10
|
+
copyContextFields,
|
|
11
|
+
applyContextFields,
|
|
12
|
+
PICKER_CONTEXT_FIELDS,
|
|
13
|
+
} from './checkout-button-trigger';
|
|
6
14
|
|
|
7
15
|
const VARIATION_MODAL_CLASS_PREFIX = 'newspack-blocks__modal-variation';
|
|
8
16
|
const IFRAME_NAME = 'newspack_modal_checkout_iframe';
|
|
@@ -220,6 +228,46 @@ describe( 'resolveCheckoutButtonForm', () => {
|
|
|
220
228
|
expect( pickerForm.querySelector( 'input[name="after_success_button_label"]' ).value ).toBe( 'Thanks!' );
|
|
221
229
|
expect( pickerForm.querySelector( 'input[name="after_success_url"]' ).value ).toBe( '/welcome/' );
|
|
222
230
|
} );
|
|
231
|
+
|
|
232
|
+
// A button locked to one variation was configured for that variation, so its
|
|
233
|
+
// coupon should not follow the reader to a different one when an unlocked
|
|
234
|
+
// button for the same product is available to supply the context instead.
|
|
235
|
+
it( 'prefers an unlocked button over a variation-locked one for the picker context', () => {
|
|
236
|
+
const locked = `<div class="wp-block-newspack-blocks-checkout-button"><form data-checkout='${ JSON.stringify( {
|
|
237
|
+
product_id: '1406',
|
|
238
|
+
variation_id: '1408',
|
|
239
|
+
is_variable: true,
|
|
240
|
+
} ) }'><input type="hidden" name="coupon" value="LOCKED20"><button type="submit">Annual</button></form></div>`;
|
|
241
|
+
const unlocked = `<div class="wp-block-newspack-blocks-checkout-button"><form data-checkout='${ JSON.stringify( {
|
|
242
|
+
product_id: '1406',
|
|
243
|
+
is_variable: true,
|
|
244
|
+
} ) }'><input type="hidden" name="coupon" value="ANYTIER5"><button type="submit">Subscribe</button></form></div>`;
|
|
245
|
+
const root = render( locked + unlocked + variationPicker( '1406', [ '1407', '1408', '1409' ] ) );
|
|
246
|
+
const pickerForm = root.querySelector( `.${ VARIATION_MODAL_CLASS_PREFIX } form` );
|
|
247
|
+
|
|
248
|
+
const result = resolveCheckoutButtonForm( root, '1406', '1407', PICKER_OPTIONS );
|
|
249
|
+
|
|
250
|
+
expect( result ).toBe( pickerForm );
|
|
251
|
+
expect( pickerForm.querySelector( 'input[name="coupon"]' ).value ).toBe( 'ANYTIER5' );
|
|
252
|
+
} );
|
|
253
|
+
|
|
254
|
+
// With nothing but locked buttons there is no correct donor, so the first in
|
|
255
|
+
// DOM order supplies the context — the other half of findContextDonorForm.
|
|
256
|
+
it( 'falls back to the first locked button when no unlocked one exists', () => {
|
|
257
|
+
const locked = ( variationId, coupon ) =>
|
|
258
|
+
`<div class="wp-block-newspack-blocks-checkout-button"><form data-checkout='${ JSON.stringify( {
|
|
259
|
+
product_id: '1406',
|
|
260
|
+
variation_id: variationId,
|
|
261
|
+
is_variable: true,
|
|
262
|
+
} ) }'><input type="hidden" name="coupon" value="${ coupon }"><button type="submit">Buy</button></form></div>`;
|
|
263
|
+
const root = render( locked( '1408', 'FIRST20' ) + locked( '1409', 'SECOND10' ) + variationPicker( '1406', [ '1407', '1408', '1409' ] ) );
|
|
264
|
+
const pickerForm = root.querySelector( `.${ VARIATION_MODAL_CLASS_PREFIX } form` );
|
|
265
|
+
|
|
266
|
+
const result = resolveCheckoutButtonForm( root, '1406', '1407', PICKER_OPTIONS );
|
|
267
|
+
|
|
268
|
+
expect( result ).toBe( pickerForm );
|
|
269
|
+
expect( pickerForm.querySelector( 'input[name="coupon"]' ).value ).toBe( 'FIRST20' );
|
|
270
|
+
} );
|
|
223
271
|
} );
|
|
224
272
|
|
|
225
273
|
describe( 'copyContextFields', () => {
|
|
@@ -263,4 +311,98 @@ describe( 'copyContextFields', () => {
|
|
|
263
311
|
expect( () => copyContextFields( null, target ) ).not.toThrow();
|
|
264
312
|
expect( () => copyContextFields( target, null ) ).not.toThrow();
|
|
265
313
|
} );
|
|
314
|
+
|
|
315
|
+
// The picker form replaces the button's own form, so a coupon attached to the
|
|
316
|
+
// Checkout Button block is only auto-applied if it is carried across.
|
|
317
|
+
it( 'copies the auto-applied coupon to the picker form', () => {
|
|
318
|
+
const root = render( '<form id="src"><input type="hidden" name="coupon" value="MEMBER10"></form><form id="dst"></form>' );
|
|
319
|
+
|
|
320
|
+
copyContextFields( root.querySelector( '#src' ), root.querySelector( '#dst' ) );
|
|
321
|
+
|
|
322
|
+
expect( root.querySelector( '#dst input[name="coupon"]' ).value ).toBe( 'MEMBER10' );
|
|
323
|
+
} );
|
|
324
|
+
} );
|
|
325
|
+
|
|
326
|
+
describe( 'applyContextFields', () => {
|
|
327
|
+
// The picker is rendered once per parent product and shared by every button
|
|
328
|
+
// targeting it, and nothing clears it when the modal closes. These two cases
|
|
329
|
+
// are what the click path gets wrong if the stamp is not authoritative.
|
|
330
|
+
const picker = () => render( '<form id="picker"></form>' ).querySelector( '#picker' );
|
|
331
|
+
const couponValue = form => {
|
|
332
|
+
const input = form.querySelector( 'input[name="coupon"]' );
|
|
333
|
+
return input ? input.value : null;
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
it( 'replaces a coupon left behind by a previously clicked button', () => {
|
|
337
|
+
const form = picker();
|
|
338
|
+
|
|
339
|
+
applyContextFields( form, { coupon: 'SAVE20' } );
|
|
340
|
+
applyContextFields( form, { coupon: 'MEMBER10' } );
|
|
341
|
+
|
|
342
|
+
expect( couponValue( form ) ).toBe( 'MEMBER10' );
|
|
343
|
+
expect( form.querySelectorAll( 'input[name="coupon"]' ) ).toHaveLength( 1 );
|
|
344
|
+
} );
|
|
345
|
+
|
|
346
|
+
it( 'clears the coupon when the clicked button has none', () => {
|
|
347
|
+
const form = picker();
|
|
348
|
+
|
|
349
|
+
applyContextFields( form, { coupon: 'SAVE20' } );
|
|
350
|
+
applyContextFields( form, {} );
|
|
351
|
+
|
|
352
|
+
expect( couponValue( form ) ).toBeNull();
|
|
353
|
+
} );
|
|
354
|
+
|
|
355
|
+
it( 'does not leave an empty coupon input that would block a later button', () => {
|
|
356
|
+
const form = picker();
|
|
357
|
+
|
|
358
|
+
applyContextFields( form, {} );
|
|
359
|
+
applyContextFields( form, { coupon: 'SAVE20' } );
|
|
360
|
+
|
|
361
|
+
expect( couponValue( form ) ).toBe( 'SAVE20' );
|
|
362
|
+
} );
|
|
363
|
+
|
|
364
|
+
it( 'stamps the after-success and attribution context', () => {
|
|
365
|
+
const form = picker();
|
|
366
|
+
|
|
367
|
+
applyContextFields( form, { after_success_behavior: 'custom', gate_post_id: 12, prompt_title: '' } );
|
|
368
|
+
|
|
369
|
+
expect( form.querySelector( 'input[name="after_success_behavior"]' ).value ).toBe( 'custom' );
|
|
370
|
+
expect( form.querySelector( 'input[name="gate_post_id"]' ).value ).toBe( '12' );
|
|
371
|
+
expect( form.querySelector( 'input[name="prompt_title"]' ) ).toBeNull();
|
|
372
|
+
} );
|
|
373
|
+
|
|
374
|
+
it( 'leaves the picker’s own fields alone', () => {
|
|
375
|
+
const form = render(
|
|
376
|
+
'<form id="picker"><input type="hidden" name="newspack_checkout" value="1"><input type="radio" name="product_id" value="9"></form>'
|
|
377
|
+
).querySelector( '#picker' );
|
|
378
|
+
|
|
379
|
+
applyContextFields( form, { coupon: 'SAVE20' } );
|
|
380
|
+
|
|
381
|
+
expect( form.querySelector( 'input[name="newspack_checkout"]' ).value ).toBe( '1' );
|
|
382
|
+
expect( form.querySelector( 'input[name="product_id"]' ).value ).toBe( '9' );
|
|
383
|
+
} );
|
|
384
|
+
|
|
385
|
+
it( 'does not throw on a null form or missing data', () => {
|
|
386
|
+
const form = picker();
|
|
387
|
+
expect( () => applyContextFields( null, { coupon: 'X' } ) ).not.toThrow();
|
|
388
|
+
expect( () => applyContextFields( form, null ) ).not.toThrow();
|
|
389
|
+
} );
|
|
390
|
+
} );
|
|
391
|
+
|
|
392
|
+
describe( 'PICKER_CONTEXT_FIELDS', () => {
|
|
393
|
+
// modal.js reads this same list for the click path, so a field missing here is
|
|
394
|
+
// dropped by both the URL trigger and the variation picker.
|
|
395
|
+
it( 'carries the coupon alongside the after-success and attribution context', () => {
|
|
396
|
+
expect( PICKER_CONTEXT_FIELDS ).toEqual(
|
|
397
|
+
expect.arrayContaining( [
|
|
398
|
+
'after_success_behavior',
|
|
399
|
+
'after_success_url',
|
|
400
|
+
'after_success_button_label',
|
|
401
|
+
'gate_post_id',
|
|
402
|
+
'newspack_popup_id',
|
|
403
|
+
'prompt_title',
|
|
404
|
+
'coupon',
|
|
405
|
+
] )
|
|
406
|
+
);
|
|
407
|
+
} );
|
|
266
408
|
} );
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
getCheckoutData,
|
|
25
25
|
getFormattedAmount,
|
|
26
26
|
} from './utils';
|
|
27
|
-
import { resolveCheckoutButtonForm, readCheckoutData } from './checkout-button-trigger';
|
|
27
|
+
import { resolveCheckoutButtonForm, readCheckoutData, applyContextFields } from './checkout-button-trigger';
|
|
28
28
|
import { applyCtaAttribution } from '../shared/js/cta-attribution';
|
|
29
29
|
|
|
30
30
|
const CLASS_PREFIX = newspackBlocksModal.newspack_class_prefix;
|
|
@@ -363,20 +363,10 @@ domReady( () => {
|
|
|
363
363
|
const variationModal = [ ...variationModals ].find( modal => modal.dataset.productId === checkoutData.product_id );
|
|
364
364
|
if ( variationModal ) {
|
|
365
365
|
variationModal.querySelectorAll( `form[target="${ IFRAME_NAME }"]` ).forEach( singleVariationForm => {
|
|
366
|
-
// Fill in the hidden params in the variation modal.
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
'after_success_button_label',
|
|
371
|
-
'gate_post_id',
|
|
372
|
-
'newspack_popup_id',
|
|
373
|
-
'prompt_title',
|
|
374
|
-
].forEach( hiddenParam => {
|
|
375
|
-
const existingInputs = singleVariationForm.querySelectorAll( 'input[name="' + hiddenParam + '"]' );
|
|
376
|
-
if ( 0 === existingInputs.length ) {
|
|
377
|
-
singleVariationForm.prepend( createHiddenInput( hiddenParam, checkoutData[ hiddenParam ] ) );
|
|
378
|
-
}
|
|
379
|
-
} );
|
|
366
|
+
// Fill in the hidden params in the variation modal. The picker is
|
|
367
|
+
// shared by every button for this product and is never reset, so
|
|
368
|
+
// this overwrites the previous open's context rather than adding to it.
|
|
369
|
+
applyContextFields( singleVariationForm, checkoutData );
|
|
380
370
|
|
|
381
371
|
// Append the product data hidden inputs.
|
|
382
372
|
const data = readCheckoutData( singleVariationForm );
|