
<script>
/**
* Product Image ? Quick View interceptor
* Deferred until jQuery and the DOM are both ready.
*/
document.addEventListener('DOMContentLoaded', function () {
var interval = setInterval(function () {
if (typeof jQuery === 'undefined') return;
clearInterval(interval);
jQuery('body').on('click', '.listing_product a[href*="/Products/details/"] img, .listing_product a[href*="/Products/details/"]', function (e) {
var $link = jQuery(this).closest('a[href*="/Products/details/"]');
// Only intercept the image link, not the product name text link
if ($link.find('img').length === 0 && !jQuery(this).is('img')) {
return;
}
e.preventDefault();
e.stopImmediatePropagation();
var $card = $link.closest('.listing_product');
var $qvBtn = $card.find('button.addBasket');
if ($qvBtn.length) {
$qvBtn.trigger('click');
}
});
}, 50);
});
</script>
<script>
/**
* Product Image ? Quick View interceptor
* Deferred until jQuery and the DOM are both ready.
*/
document.addEventListener('DOMContentLoaded', function () {
var interval = setInterval(function () {
if (typeof jQuery === 'undefined') return;
clearInterval(interval);
jQuery('body').on('click', '.listing_product a[href*="/Products/details/"] img, .listing_product a[href*="/Products/details/"]', function (e) {
var $link = jQuery(this).closest('a[href*="/Products/details/"]');
// Only intercept the image link, not the product name text link
if ($link.find('img').length === 0 && !jQuery(this).is('img')) {
return;
}
e.preventDefault();
e.stopImmediatePropagation();
var $card = $link.closest('.listing_product');
var $qvBtn = $card.find('button.addBasket');
if ($qvBtn.length) {
$qvBtn.trigger('click');
}
});
}, 50);
});
</script>
<script>
// =====================================================
// CONFIG — edit these values to control the widget
// =====================================================
var MP_CONFIG = {
activeStep: 3, // 3 = Choose gift | 2 = Campus Store | 3 = Donation | 4 = Basket
loadDelay: 600, // ms to wait after page load before animating
animDuration: 800 // ms for the fill line to reach the active step
};
// =====================================================
var steps = document.querySelectorAll('.mp-step');
var fill = document.getElementById('mp-fill');
function setStep(n) {
MP_CONFIG.activeStep = n;
steps.forEach(function(s) {
var i = parseInt(s.getAttribute('data-step'));
s.classList.remove('done', 'active');
if (i < n xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed xss=removed fill.style.transition = 'none' fill.style.width = '0px' fill.style.transition = 'width '>
<script>
(function(){
const NAME = ".dropdown-item strong";
const BAL = ".balance";
const BASKET = "#basket_points";
const first = (s)=> (s||"").trim().split(/\s+/)[0] || "there";
const extractPoints = (el)=>{
if(!el) return "0";
const k = el?.cloneNode?.(true);
if(!k) return "0";
k.querySelectorAll("span").forEach(n=>n.remove());
const m = (k.textContent||"").match(/\d[\d,.\s]*/);
return m ? m[0].replace(/[^\d]/g,"") || "0" : "0";
};
const nameText = document.querySelector(NAME)?.textContent || "";
const points = extractPoints(document.querySelector(BAL)) || "122";
const basketPoints = extractPoints(document.querySelector(BASKET)) || "0";
const fname = first(nameText);
const totalNum = parseInt(points, 10) || 0;
const basketNum = parseInt(basketPoints, 10) || 0;
const remaining = totalNum - basketNum;
function showBubble(){
const style = document.createElement("style");
style.textContent = `
.trw-bubble {
position: fixed; bottom: 24px; right: 24px;
background: #006CE3;
color: #fff;
border-radius: 20px;
padding: 22px 28px;
max-width: 360px;
box-shadow: 0 12px 28px rgba(0,0,0,.35);
z-index: 2147483000;
display: flex; align-items: center; gap: 16px;
line-height: 1.35;
isolation: isolate;
}
.trw-icon { width: 40px; height: 40px; flex: 0 0 auto; }
.trw-content { flex: 1; min-width: 0; }
.trw-title { font-weight: 700; font-size: 18px; margin: 0 0 6px; }
.trw-line { margin: 0; font-size: 15px; opacity: .96; }
.trw-line strong { font-weight: 800; }
.trw-close {
position: absolute;
top: -10px; right: -10px;
width: 28px; height: 28px;
border-radius: 999px;
border: 0;
background: rgba(0,0,0,.6);
color: #fff;
display: grid; place-items: center;
cursor: pointer;
box-shadow: 0 4px 10px rgba(0,0,0,.25);
}
.trw-close svg { width: 14px; height: 14px; stroke: currentColor; stroke-width: 3; fill: none; stroke-linecap: round; }
.trw-close:focus { outline: 2px solid #2563eb; outline-offset: 2px; }
.trw-bubble[data-state="enter"] { opacity: 0; transform: translateY(12px) scale(.92); }
.trw-bubble[data-anim="in"] { animation: trw_pop_in .42s cubic-bezier(.2,.82,.2,1.2) forwards; }
.trw-bubble[data-anim="out"] { animation: trw_fade_out .28s ease forwards; }
@keyframes trw_pop_in {
0% { opacity:0; transform: translateY(12px) scale(.92); }
60% { opacity:1; transform: translateY(0) scale(1.06); }
100% { opacity:1; transform: translateY(0) scale(1); }
}
@keyframes trw_fade_out {
to { opacity:0; transform: translateY(12px) scale(.95); }
}
@media (prefers-reduced-motion: reduce) {
.trw-bubble[data-anim="in"], .trw-bubble[data-anim="out"] { animation: none !important; }
}
@media (max-width: 600px){
.trw-bubble {
left: 50%; right: auto;
transform: translateX(-50%);
max-width: min(92vw, 420px);
padding: 20px 22px;
}
}
`;
const bubble = document.createElement("div");
bubble.className = "trw-bubble";
bubble.setAttribute("role","status");
bubble.setAttribute("aria-live","polite");
bubble.setAttribute("data-state","enter");
bubble.setAttribute("data-anim","in");
const spendingLine = remaining > 0
? `You have
${remaining} Coins left to spend`
: `You've reached your spending limit!
0 Coins left`;
bubble[removed] = `
<button class="trw-close" aria-label="Close">
<svg viewBox="0 0 24 24">
</svg>
</button>
Hey ${fname},
${spendingLine}
`;
document.head.appendChild(style);
document.body.appendChild(bubble);
const headingEl = document.querySelector("h1, h2, h3") || document.body;
const headingFont = getComputedStyle(headingEl).fontFamily;
const bodyFont = getComputedStyle(document.body).fontFamily;
bubble.style.fontFamily = bodyFont;
bubble.querySelector(".trw-title").style.fontFamily = headingFont;
const cleanup = () => {
bubble.setAttribute("data-anim","out");
setTimeout(() => { bubble.remove(); style.remove(); }, 300);
};
bubble.querySelector(".trw-close").addEventListener("click", cleanup);
document.addEventListener("keydown", function esc(e){
if(e.key==="Escape"){ cleanup(); document.removeEventListener("keydown",esc); }
});
}
setTimeout(showBubble, 1000);
})();
</script>