Skip to content

Commit cfab1fe

Browse files
committed
preload checkoput page
1 parent d4669f1 commit cfab1fe

2 files changed

Lines changed: 161 additions & 1 deletion

File tree

CustomerData/Cart.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public function renderCartHtml($data)
6969
7070
<div class="actions">
7171
<div class="primary">
72-
<button id="top-cart-btn-checkout" type="button" class="action primary checkout" data-action="close" onclick="window.location.href=\'/checkout/\'" title="Proceed to Checkout">Proceed to Checkout</button>
72+
<button id="top-cart-btn-checkout" type="button" class="action primary checkout" data-action="close" title="Proceed to Checkout">Proceed to Checkout</button>
7373
</div>
7474
</div>
7575

view/frontend/templates/cart-js.phtml

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,166 @@ document.addEventListener('DOMContentLoaded', function() {
8989

9090
});
9191
</script>
92+
<script>
93+
// --- config ---
94+
const CHECKOUT_URL = '/checkout/';
95+
const TIMEOUT = 2000;
96+
97+
// Feature detect Speculation Rules
98+
const supportsSpeculation =
99+
typeof HTMLScriptElement?.supports === 'function' &&
100+
HTMLScriptElement.supports('speculationrules');
101+
102+
function prerenderCheckout() {
103+
if (!supportsSpeculation) return;
104+
if (document.querySelector(`script[data-prerender="${CHECKOUT_URL}"]`)) return;
105+
106+
console.log('Creating speculation rules for checkout prerender');
107+
const s = document.createElement('script');
108+
s.type = 'speculationrules';
109+
s.dataset.prerender = CHECKOUT_URL;
110+
s.textContent = JSON.stringify({
111+
prerender: [{ source: 'list', urls: [CHECKOUT_URL] }]
112+
});
113+
document.head.appendChild(s);
114+
}
115+
116+
function createPreloader() {
117+
const preloader = document.createElement('div');
118+
preloader.id = 'checkout-preloader';
119+
preloader.style.cssText = `
120+
position: fixed;
121+
top: 0;
122+
left: 0;
123+
width: 100%;
124+
height: 100%;
125+
background: rgba(255, 60, 60, 0.8);
126+
display: flex;
127+
flex-direction: column;
128+
justify-content: center;
129+
align-items: center;
130+
z-index: 9999;
131+
color: white;
132+
font-family: Arial, sans-serif;
133+
`;
134+
135+
preloader.innerHTML = `
136+
<div class="spinner" style="
137+
width: 50px;
138+
height: 50px;
139+
border: 4px solid rgba(255, 255, 255, 0.3);
140+
border-top: 4px solid white;
141+
border-radius: 50%;
142+
animation: spin 1s linear infinite;
143+
margin-bottom: 20px;
144+
"></div>
145+
<div class="message" style="
146+
font-size: 18px;
147+
font-weight: bold;
148+
margin-bottom: 10px;
149+
">Preparing Checkout...</div>
150+
<div class="submessage" id="loading-message" style="
151+
font-size: 14px;
152+
opacity: 0.8;
153+
min-height: 20px;
154+
text-align: center;
155+
">Loading your cart and payment options</div>
156+
`;
157+
158+
// Add CSS animation
159+
const style = document.createElement('style');
160+
style.textContent = `
161+
@keyframes spin {
162+
0% { transform: rotate(0deg); }
163+
100% { transform: rotate(360deg); }
164+
}
165+
@keyframes fadeInOut {
166+
0%, 100% { opacity: 0.3; }
167+
50% { opacity: 1; }
168+
}
169+
`;
170+
document.head.appendChild(style);
171+
172+
return preloader;
173+
}
174+
175+
function startLoadingMessages() {
176+
const loadingMessages = [
177+
'Loading your cart and payment options...',
178+
'Calculating shipping costs...',
179+
'Processing tax calculations...',
180+
'Preparing payment methods...',
181+
'Loading checkout form...',
182+
'Setting up secure checkout...',
183+
'Almost ready...'
184+
];
185+
186+
let messageIndex = 0;
187+
const messageElement = document.getElementById('loading-message');
188+
189+
if (messageElement) {
190+
const updateMessage = () => {
191+
messageElement.style.animation = 'fadeInOut 0.5s ease-in-out';
192+
messageElement.textContent = loadingMessages[messageIndex];
193+
194+
messageIndex = (messageIndex + 1) % loadingMessages.length;
195+
196+
// Schedule next message
197+
setTimeout(updateMessage, TIMEOUT / (loadingMessages.length + 1));
198+
};
199+
200+
// Start the message cycle
201+
updateMessage();
202+
}
203+
}
204+
205+
function showPreloader() {
206+
const preloader = createPreloader();
207+
document.body.appendChild(preloader);
208+
console.log('Checkout preloader shown');
209+
210+
// Start cycling through loading messages
211+
startLoadingMessages();
212+
}
213+
214+
function hidePreloader() {
215+
const preloader = document.getElementById('checkout-preloader');
216+
if (preloader) {
217+
preloader.remove();
218+
console.log('Checkout preloader hidden');
219+
}
220+
}
221+
222+
function handleCheckoutClick(e) {
223+
if (e.target.closest('#top-cart-btn-checkout')) {
224+
const el = e.target.closest('#top-cart-btn-checkout');
225+
if (el.tagName === 'A') e.preventDefault();
226+
227+
// Ensure prerender is started (in case pointer down didn't fire)
228+
prerenderCheckout();
229+
230+
// Show preloader
231+
showPreloader();
232+
233+
console.log('Checkout clicked, waiting 5 seconds before navigation');
234+
setTimeout(() => {
235+
hidePreloader();
236+
window.location.href = CHECKOUT_URL;
237+
}, TIMEOUT);
238+
}
239+
}
240+
241+
// Start prerender as early as possible on press
242+
function handlePointerDown(e) {
243+
if (e.target.closest('#top-cart-btn-checkout')) prerenderCheckout();
244+
}
245+
246+
// Use delegation so it works even if the button is injected later
247+
document.addEventListener('pointerdown', handlePointerDown, true);
248+
document.addEventListener('click', handleCheckoutClick, true);
249+
250+
</script>
251+
92252
<style>
93253
.minicart-items .action.edit:before {
94254
-webkit-font-smoothing: antialiased;

0 commit comments

Comments
 (0)