@@ -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