1//Updated Reserve Your Yamaha/SYR/DX Script 2 3// Create a debounce function 4function debounce(func, delay) { 5 let timer; 6 return function (...args) { 7 const context = this; 8 clearTimeout(timer); // Clear the previous timer 9 timer = setTimeout(() => func.apply(context, args), delay); 10 }; 11} 12 13function parseURLComponents(url) { 14 try { 15 // Create a new URL object 16 const parsedUrl = new URL(url); 17 18 // Extract the components of the URL 19 const components = { 20 href: parsedUrl.href, // The full URL 21 protocol: parsedUrl.protocol, // Protocol (e.g., 'http:' or 'https:') 22 host: parsedUrl.host, // Hostname and port (e.g., 'example.com:80') 23 hostname: parsedUrl.hostname, // Hostname (e.g., 'example.com') 24 port: parsedUrl.port, // Port (e.g., '80') 25 pathname: parsedUrl.pathname, // Path (e.g., '/path/to/resource') 26 search: parsedUrl.search, // Query string (e.g., '?key=value') 27 searchParams: parsedUrl.searchParams, // URLSearchParams object to handle query parameters 28 hash: parsedUrl.hash, // Fragment identifier (e.g., '#section') 29 }; 30 31 // Convert URLSearchParams to a plain object 32 components.queryParams = {}; 33 parsedUrl.searchParams.forEach((value, key) => { 34 components.queryParams[key] = value; 35 }); 36 37 return components; 38 } catch (error) { 39 console.error("Invalid URL:", error); 40 return; 41 } 42} 43 44async function trackReserveOnlineEvent(vin, productId) { 45 try { 46 // Send Tracking Event 47 const reservationUrl = parseURLComponents(window.location.href); 48 49 const trackingBody = { 50 link_name: "RYY", 51 url: reservationUrl.href, 52 product_id: productId || reservationUrl.queryParams?.product_id, 53 vin: vin || reservationUrl.queryParams?.vin, 54 }; 55 56 const response = await fetch( 57 `${window.location.origin}/D360.php?action=track-reservation`, 58 { 59 method: "POST", 60 headers: { 61 "Content-Type": "application/x-www-form-urlencoded", 62 }, 63 body: new URLSearchParams(trackingBody), 64 } 65 ); 66 67 if (!response.ok) { 68 throw new Error("Network response was not ok"); 69 } 70 71 const data = await response.json(); 72 73 if (data.error) { 74 throw new Error(data.error); 75 } 76 } catch (e) { 77 console.error(e); 78 } 79} 80 81async function reserveOnline(id, dealer, reserveTerms, productId) { 82 try { 83 if (!id || !id.length) { 84 return; 85 } 86 87 const reserveUrl = parseURLComponents(window.location.href); 88 const dxEnv = 89 reserveUrl.queryParams?.dxEnv === "staging" ? "staging" : "prod"; 90 91 // Set Tracking Event Data 92 const trackingBody = { 93 link_name: "RYY", 94 url: reserveUrl.href, 95 product_id: productId || reserveUrl.queryParams?.product_id, 96 vin: id || reserveUrl.queryParams?.vin, 97 }; 98 99 // Set Parameters For Fetch Request 100 const body = new URLSearchParams(); 101 body.append("id", id); 102 body.append("dealer", dealer); 103 body.append("dxEnv", dxEnv); 104 body.append("trackingData", JSON.stringify(trackingBody)); 105 if (reserveTerms) { 106 body.append("reserveTerms", reserveTerms); 107 } 108 109 // Execute Fetch Request To Get Reservation Data 110 const response = await fetch( 111 `${window.location.origin}/D360.php?action=reservation-data`, 112 { 113 method: "POST", 114 headers: { 115 "Content-Type": "application/x-www-form-urlencoded", // Set Content-Type to URL-encoded form 116 }, 117 body: body.toString(), 118 } 119 ); 120 121 if (!response.ok) { 122 throw new Error("Network response was not ok"); 123 } 124 125 const data = await response.json(); 126 127 if (!data || !Object.keys(data).length) { 128 throw new Error("No Reservation Data Recieved"); 129 } 130 131 // Remove Any Existing Reserve Online Form 132 const existingForm = document.getElementById("reserve-online-form"); 133 if (existingForm) { 134 existingForm.remove(); 135 } 136 137 const submissionUrl = 138 dxEnv === "staging" 139 ? "https://yamaha-react-web-stage.sandbox.yamaha-motor.com/p/" 140 : "https://yamaha-motor.com/p/"; 141 142 // Create Form & Submit To Reserve Online 143 const f = document.createElement("form"); 144 f.setAttribute("method", "POST"); 145 // Staging URL - Update Base URL for Production 146 f.setAttribute("action", `${submissionUrl}${data.slug}`); 147 f.setAttribute("target", "_blank"); 148 f.setAttribute("id", "reserve-online-form"); 149 150 const modelDataInput = document.createElement("input"); 151 modelDataInput.setAttribute("type", "hidden"); 152 modelDataInput.setAttribute("name", "modelData"); 153 modelDataInput.setAttribute("value", JSON.stringify(data.reservation)); 154 155 f.append(modelDataInput); 156 157 // // Send Tracking Event 158 // trackReserveOnlineEvent(id, productId); 159 160 document.querySelectorAll("body")[0].append(f); 161 f.submit(); 162 } catch (e) { 163 console.error(e); 164 throw e; 165 } 166} 167 168async function handleReserveOnlineClick(button) { 169 // Disable Button 170 button.disabled = true; 171 172 if (!button.dataset.vin) { 173 button.disabled = false; 174 return; 175 } 176 177 let dealer; 178 if (button.dataset?.mfg_dealer_number) { 179 dealer = button.dataset.mfg_dealer_number; 180 } else { 181 // Attempt to get dealer number from URL 182 const queryString = window.location.search;
183 const urlParams = new URLSearchParams(queryString); 184 dealer = urlParams.get("mfg_dealer_number"); 185 } 186 187 if (!dealer) { 188 button.disabled = false; 189 return; 190 } 191 192 let reserveTerms; 193 if (button.dataset?.reserve_terms) { 194 reserveTerms = button.dataset.reserve_terms; 195 } 196 197 let productId = button.dataset?.product_id || null; 198 199 await reserveOnline(button.dataset.vin, dealer, reserveTerms, productId); 200 201 // Enable Button 202 button.disabled = false; 203} 204 205function applyReserveEventListeners() { 206 const reserveOnlineButtons = document.querySelectorAll(".reserve-online"); 207 208 reserveOnlineButtons.forEach((button) => { 209 // remove existing event listeners 210 const newButton = button.cloneNode(true); 211 212 button.parentNode.replaceChild(newButton, button); 213 214 newButton.addEventListener( 215 "click", 216 debounce(() => { 217 handleReserveOnlineClick(newButton); 218 }, 500), 219 { once: true } 220 ); 221 }); 222} 223 224document.addEventListener("DOMContentLoaded", function () { 225 applyReserveEventListeners(); 226});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.