function ZgLibrary() { const loaderClass = 'zg-loading'; function showLoader() { const loader = document.createElement('div'); loader.className = loaderClass; const loaderImage = document.createElement('img'); loaderImage.src = 'https://cdn.prod.website-files.com/5fb2b92b11680d48c6faa1ed/5fb2b92b11680d4081faa442_preloader.gif'; loaderImage.alt = 'Loading...'; loader.appendChild(loaderImage); document.body.appendChild(loader); } function hideLoader() { const loaders = document.body.querySelectorAll(`.${loaderClass}`); loaders.forEach((loader) => { document.body.removeChild(loader); }); } function getConstants() { let constants = {}; constants.annual = 'Annual'; constants.monthly = 'Monthly'; constants.any = 'Any'; constants.alacarte = 'ALaCarte'; constants.researcher = 'Researcher'; constants.seller = 'Seller'; constants.plans = [{ period: constants.monthly, type: constants.researcher, selectors: { priceText: '.monthly-researcher-price', oldPriceText: '.monthly-researcher-old-price', originalPriceTextWrapper: '.monthly-researcher-original-price-wrapper', crossedPriceTextWrapper: '.monthly-researcher-crossed-price-wrapper', discountedPriceTextWrapper: '.monthly-researcher-discounted-price-wrapper', totalUpfrontPriceText: null, startButton: '.monthly-researcher-button', tiersContainer: null, }, }, { period: constants.monthly, type: constants.seller, selectors: { priceText: '.monthly-seller-price', oldPriceText: '.monthly-seller-old-price', originalPriceTextWrapper: '.monthly-seller-original-price-wrapper', crossedPriceTextWrapper: '.monthly-seller-crossed-price-wrapper', discountedPriceTextWrapper: '.monthly-seller-discounted-price-wrapper', totalUpfrontPriceText: null, startButton: '.monthly-seller-button', tiersContainer: '.monthly-seller-tier-container', }, }, { period: constants.annual, type: constants.researcher, selectors: { priceText: '.annual-researcher-price', oldPriceText: '.annual-researcher-old-price', originalPriceTextWrapper: '.annual-researcher-original-price-wrapper', crossedPriceTextWrapper: '.annual-researcher-crossed-price-wrapper', discountedPriceTextWrapper: '.annual-researcher-discounted-price-wrapper', totalUpfrontPriceText: '.annual-researcher-total-price', startButton: '.annual-researcher-button', tiersContainer: null, }, }, { period: constants.annual, type: constants.seller, selectors: { priceText: '.annual-seller-price', oldPriceText: '.annual-seller-old-price', originalPriceTextWrapper: '.annual-seller-original-price-wrapper', crossedPriceTextWrapper: '.annual-seller-crossed-price-wrapper', discountedPriceTextWrapper: '.annual-seller-discounted-price-wrapper', totalUpfrontPriceText: '.annual-seller-total-price', startButton: '.annual-seller-button', tiersContainer: '.annual-seller-tier-container', }, }]; constants.sellerTiersSelectors = { priceText: '.seller-tier-price', oldPriceText: '.seller-tier-old-price', originalPriceTextWrapper: '.seller-tier-original-price-wrapper', crossedPriceTextWrapper: '.seller-tier-crossed-price-wrapper', discountedPriceTextWrapper: '.seller-tier-discounted-price-wrapper', totalUpfrontPriceText: '.seller-tier-total-price', }; constants.annualButtonId = 'annualButtonId'; constants.monthlyButtonId = 'monthlyButtonId'; constants.buttonActiveClass = 'w--current'; constants.couponElementId = 'couponElementId'; return constants; }; function initPeriod() { const constants = getConstants(); try { const period = getParameterByName('period'); new MutationObserver(() => { try { changeUrlWithPeriod(); } catch (e) { console.log(e); } }).observe(document.getElementById(constants.annualButtonId), { childList: true, subtree: true, attributes: true }); activateTab(period); } catch (e) { console.log(e); } } function initCoupon() { const couponId = readCookie('zg-coupon'); if (couponId) { setCouponData(couponId, applyCoupon); } }; function getParameterByName(name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, '\\$&'); var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, ' ')); }; function activateTab(period) { const constants = getConstants(); let newButtonId; if (!period) return; if (period.toLowerCase() === 'monthly') { newButtonId = constants.monthlyButtonId; } else if (period.toLowerCase() === 'annual') { newButtonId = constants.annualButtonId; } if (newButtonId) document.getElementById(newButtonId).click(); }; function changeUrlWithPeriod() { const constants = getConstants(); const period = document.getElementById(constants.annualButtonId).classList.contains(constants.buttonActiveClass) ? 'annual' : 'monthly'; let newUrl = new URL(document.location); newUrl.searchParams.set("period", period); history.replaceState(null, null, newUrl.href); }; function readCookie(name) { name += '='; for (var ca = document.cookie.split(/;\s*/), i = ca.length - 1; i >= 0; i--) { if (!ca[i].indexOf(name)) { return ca[i].replace(name, ''); } } }; function applyCoupon(coupon) { const constants = getConstants(); try { if (!coupon.availableForPeriod || !coupon.availableForPlans) return; if (coupon.availableForPlans === constants.alacarte) return; for (let i = 0; i < constants.plans.length; i++) { const plan = constants.plans[i]; const isCouponValidForPlan = isCouponValidForPeriodPlan(coupon, plan.period, plan.type); if (!isCouponValidForPlan) { continue; } // Apply the coupon for all elements in the page where we display researcher or seller prices applyCouponForPlan(plan, coupon, document); // Apply the coupon for all seller tiers const tiersContainers = Array.from(document.querySelectorAll(plan.selectors.tiersContainer)); for (var j = 0; j < tiersContainers.length; j++) { const tiersContainer = tiersContainers[j]; const tier = { period: plan.period, selectors: constants.sellerTiersSelectors }; applyCouponForPlan(tier, coupon, tiersContainer); } } } catch (e) { console.log(e); } }; function applyCouponForPlan(plan, coupon, rootElement) { const constants = getConstants(); let planState = populatePlanStateFromPage(plan, rootElement); if (plan.period === constants.monthly) { planState = calculateNewMonthlyState(planState, coupon); } else if (plan.period === constants.annual) { planState = calculateNewAnnualState(planState, coupon); } updatePagePlanState(plan, planState, rootElement); } function populatePlanStateFromPage(plan, rootElement) { rootElement = rootElement || document; const constants = getConstants(); const price = Number.parseInt(rootElement.querySelector(plan.selectors.priceText).innerText); const total = plan.period === constants.annual ? price * 12 : undefined; const startButton = rootElement.querySelector(plan.selectors.startButton); let startButtonText = undefined; let startButtonHref = undefined; if (startButton) { startButtonText = startButton.innerText; startButtonHref = startButton.href; } return { price: price, total: total, startButtonText: startButtonText, startButtonHref: startButtonHref, }; } function populateCouponState(pageState, coupon) { let text = 'Coupon Applied'; if (coupon.percentOff) { text = coupon.percentOff * 100 + "% Off Coupon Applied"; } else if (coupon.amountOff) { text = '$' + coupon.amountOff + " Off Coupon Applied"; } pageState.coupon.text = text; return pageState; }; function isCouponValidForPeriodPlan(coupon, period, plan) { const constants = getConstants(); return (coupon.availableForPeriod === period || coupon.availableForPeriod === constants.any) && (coupon.availableForPlans.includes(plan) || coupon.availableForPlans.includes(constants.any)); } function calculateNewMonthlyState(monthlyState, coupon) { let oldPrice = Number.parseInt(monthlyState.price); let newPrice = oldPrice; if (coupon.percentOff) { newPrice = (1 - coupon.percentOff) * oldPrice; } else if (coupon.amountOff) { newPrice = oldPrice - coupon.amountOff; } if (oldPrice !== newPrice) { monthlyState.price = Math.floor(newPrice); monthlyState.oldPrice = oldPrice; } monthlyState.startButtonText = getStartTextFromTrialPeriodInDays(coupon.trialPeriodInDays); monthlyState.startButtonHref = `${monthlyState.startButtonHref}?coupon=${coupon.couponId}`; return monthlyState; } function calculateNewAnnualState(annualState, coupon) { let oldPrice = Number.parseInt(annualState.price); let oldTotal = Number.parseInt(annualState.total); let newTotal = oldTotal; if (coupon.percentOff) { newTotal = (1 - coupon.percentOff) * oldTotal; } else if (coupon.amountOff) { newTotal = oldTotal - coupon.amountOff; } if (oldTotal !== newTotal) { annualState.price = Math.floor(newTotal / 12); annualState.oldPrice = oldPrice; annualState.total = Math.floor(newTotal); } annualState.total = formatPriceWithComma(annualState.total); annualState.startButtonText = getStartTextFromTrialPeriodInDays(coupon.trialPeriodInDays); annualState.startButtonHref = `${annualState.startButtonHref}?coupon=${coupon.couponId}`; return annualState; } function getStartTextFromTrialPeriodInDays(trialPeriodInDays) { if (trialPeriodInDays === null || trialPeriodInDays === undefined || trialPeriodInDays === 7) return undefined; if (trialPeriodInDays === 0) return 'Start Subscription'; return `Start ${trialPeriodInDays} Day Trial`; } function updatePagePlanState(plan, planState, rootElement) { rootElement = rootElement || document; updateElementsText(rootElement.querySelectorAll(plan.selectors.priceText), planState.price); updateElementsText(rootElement.querySelectorAll(plan.selectors.oldPriceText), planState.oldPrice); //hide original setElementsDisplay(rootElement.querySelectorAll(plan.selectors.originalPriceTextWrapper), 'none'); //show crossed setElementsDisplay(rootElement.querySelectorAll(plan.selectors.crossedPriceTextWrapper), 'flex'); //show discount setElementsDisplay(rootElement.querySelectorAll(plan.selectors.discountedPriceTextWrapper), 'flex'); updateElementsText(rootElement.querySelectorAll(plan.selectors.totalUpfrontPriceText), planState.total); updateElementsText(rootElement.querySelectorAll(plan.selectors.startButton), planState.startButtonText); updateElementsHref(rootElement.querySelectorAll(plan.selectors.startButton), planState.startButtonHref); } function showHideCouponElement() { const constants = getConstants(); const coupon = getCoupon(); let period = document.getElementById(constants.annualButtonId).classList.contains(constants.buttonActiveClass) ? 'annual' : 'monthly'; if (coupon.availableForPeriod.toLowerCase() == period || coupon.availableForPeriod.toLowerCase() == 'any') { document.getElementById(constants.couponElementId).style.display = 'block'; } else { document.getElementById(constants.couponElementId).style.display = 'none'; } document.getElementById(constants.couponElementId).style.cursor = 'default'; } function updateElementsText(elements, value) { if (elements && elements.forEach) { elements.forEach(el => updateElementText(el, value)); } } function updateElementText(element, value) { if (!element || value === undefined) { return; } else { element.innerText = value; } } function updateElementsHref(elements, value) { if (elements && elements.forEach) { elements.forEach(el => updateElementHref(el, value)); } } function updateElementHref(element, value) { if (!element || value === undefined) { return; } else { element.href = value; } } function setElementsDisplay(elements, cssDisplay) { if (elements && elements.forEach) { elements.forEach(el => setElementDisplay(el, cssDisplay)); } } function setElementDisplay(element, cssDisplay) { element.style.display = cssDisplay || 'block'; } function setCouponData(couponId, callback) { try { var corsCacheBuster = Date.now(); fetch(`https://my.zonguru.com/api/payment/coupon/${couponId}/settings?v=${corsCacheBuster}`) .then(response => response.json()) .then(couponData => { if (couponData && couponData.content) { window.zg_coupon = couponData.content; if (callback) callback(couponData.content); } }); } catch (e) { console.log(e) } }; function getCoupon() { if (window.zg_coupon) return window.zg_coupon; }; function formatPriceWithComma(price) { if (price < 1000) return price; var formattedPrice = price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); return formattedPrice; }; return { initCoupon: initCoupon, initPeriod: initPeriod, showLoader: showLoader, hideLoader: hideLoader, }; } window.zg_lib = ZgLibrary();