1dxp.ready(function() { 2 const $submit = $("button.submit"); 3 const $validated = "validation-success"; 4 const $formType = "quote-request"; 5 const $formLabel = "lead-quote-request"; 6 const $modelDropDown = document.querySelector(".guideFieldNode.guideDropDownList.model"); 7 const $dealerDropDown = document.querySelector(".guideFieldNode.guideDropDownList.dealer"); 8 const $modelDropDownItems = $(".guideFieldNode.guideDropDownList.model .cmp-form__dropdown-item"); 9 10 const language = window.dxp.settings.language; 11 const country = window.dxp.settings.country; 12 const brand = window.dxp.settings.brand; 13 const dealerApi = window.dxp.settings.dealer.dealerApi; 14 15 let modelName = "no model found"; 16 let modelId = "no model ID found"; 17 18 let dealerName = "no dealer found"; 19 let dealerCity = "no city found"; 20 let dealerRegion = "no region found"; 21 let dealerId = "no ID found"; 22 let dealerZip = "no zip found"; 23 24 var finalUrl = ""; 25 var dealerData; 26 27 async function hashValue(email) { 28 const encoder = new TextEncoder(); 29 const data = encoder.encode(email); 30 const hashBuffer = await crypto.subtle.digest("SHA-256", data); 31 const hashArray = Array.from(new Uint8Array(hashBuffer)); 32 return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); 33 } 34 35 //validates if all mandatory fields are filled in the currentPanel 36 function panelValidate(panelName) { 37 let panel = guideBridge.resolveNode(panelName); 38 return panel && panel.validate(); 39 } 40 41 42 modelSelected(); 43 triggerFormSubmit(); 44 45 //select model 46 function modelSelected() { 47 T1.channels.statistics.publish(dxp.constants.TOPICS_T1.STATS_TRACK, { 48 extraData: { 49 event: { 50 name: 'formevent', 51 componentName: $formType, 52 componentGroup: 'forms', 53 label: 'select-model', 54 action: 'form-step' 55 }, 56 form: { 57 name: $formLabel, 58 step: 'select-model', 59 conversion: 0 60 } 61 } 62 }); 63 } 64 65 //set product data on selected model 66 function modelSelect(mutation) { 67 var url = Granite.HTTP.externalize("/bin/form/model"); 68 var carModel = mutation.target.dataset.save; 69 var locale = document.head.querySelector('[property="og:locale"]').content; 70 var siteName = document.head.querySelector('[property="og:site_name"]').content; 71 72 var settings = { 73 "type": "GET", 74 "data": { 75 "carModel": carModel, 76 "locale": locale, 77 "siteName": siteName, 78 "form": "request-a-quote" 79 }, 80 "success": function(response) { 81 if (window.tngaDataLayer) { 82 window.tngaDataLayer.product = [response]; 83 } 84 } 85 }; 86 $.ajax(url, settings); 87 } 88 89 $modelDropDownItems.each(function() { 90 var target = this; 91 var observer = new MutationObserver(function(mutations) { 92 mutations.forEach(function(mutation) { 93 if (mutation.attributeName == 'data-selected' && mutation.target.classList.contains('selected')) { 94 modelSelect(mutation); 95 } 96 }); 97 }); 98 observer.observe(target, { 99 attributes: true 100 }); 101 }); 102 103 //Generates API URL based on the form 104 function formatAPIEndPoint() { 105 if (panelValidate("dealerPanel")) { 106 //selected dealer 107 dealerId = $dealerDropDown && $dealerDropDown.querySelector("[data-selected = true]").getAttribute("data-save"); 108 finalUrl = dealerApi + brand + '/' + country + '/' + language + '/' + dealerId; 109 if (brand !== undefined && country !== undefined && language !== undefined) { 110 return finalUrl; 111 } 112 return dealerAPI + 'toyota/gb/en/' + dealerId; 113 } 114 } 115 116 //dealer dropdown when selected 117 function dealerSelected() { 118 119 if (panelValidate("dealerPanel")) { 120 //get dealer data 121 const url = formatAPIEndPoint(brand, country, language, dealerId, dealerApi); 122 const xhttp = new XMLHttpRequest(); 123 xhttp.onreadystatechange = function() { 124 if (this.readyState == 4 && this.status == 200 && Object.keys(JSON.parse(this.responseText)).length > 1) { 125 dealerData = JSON.parse(this.responseText); 126 } 127 }; 128 129 xhttp.open("GET", url, false); 130 xhttp.send(); 131 if (dealerData && dealerData.dealers[0]) { 132 if (dealerData.dealers[0].uuid) { 133 dealerId = dealerData.dealers[0].uuid; 134 }; 135 if (dealerData.dealers[0].name) { 136 dealerName = dealerData.dealers[0].name; 137 } 138 if (dealerData.dealers[0].address.city) { 139 dealerCity = dealerData.dealers[0].address.city; 140 } 141 if (dealerData.dealers[0].address.region) { 142 dealerRegion = dealerData.dealers[0].address.region; 143 } 144 if (dealerData.dealers[0].address.zip) { 145 dealerZip = dealerData.dealers[0].address.zip; 146 } 147 } 148 taggingDealerDetails(); 149 } 150 151 } 152 153 //Selecting dealer 154 function dealerSelectedNext() { 155 if (panelValidate("model")) { 156 modelId = $modelDropDown.querySelector("[data-selected = 'true']").getAttribute("data-save"); 157 modelName = $modelDropDown.querySelector(".cmp-form__dropdown-header-value").textContent; 158 T1.channels.statistics.publish(dxp.constants.TOPICS_T1.STATS_TRACK, { 159 extraData: { 160 event: { 161 name: 'formevent', 162 componentName: $formType, 163 componentGroup: 'forms', 164 label: 'select-dealer', 165 action: 'form-step' 166 }, 167 form: { 168 name: $formLabel, 169 step: 'select-dealer', 170 conversion: 0 171 }, 172 product: [{ 173 category: 'cars', 174 subCategory: 'new-cars', 175 productInfo: { 176 tmeModelId: modelId, 177 modelName: modelName, 178 } 179 }] 180 } 181 }); 182 } 183 } 184 $submit.eq(0).on('click', dealerSelectedNext); 185 186 //Adds tagging details for dealer step 187 function taggingDealerDetails() { 188 189 T1.channels.statistics.publish(dxp.constants.TOPICS_T1.STATS_TRACK, { 190 extraData: { 191 event: { 192 name: 'formevent', 193 componentName: $formType, 194 componentGroup: 'forms', 195 action: 'form-step', 196 label: 'contact-details' 197 }, 198 form: { 199 name: $formLabel, 200 step: 'contact-details', 201 conversion: 0 202 }, 203 product: [{ 204 category: 'cars', 205 subCategory: 'new-cars', 206 productInfo: { 207 tmeModelId: modelId, 208 modelName: modelName, 209 } 210 }], 211 dealer: { 212 name: dealerName, 213 dealerId: dealerId, 214 city: dealerCity, 215 zipCode: dealerZip, 216 region: dealerRegion 217 }, 218 } 219 }); 220 } 221 222 //Check for the type of dealer 223 if (guideBridge.resolveNode("typeOfDealer").value === "dealerfinder") { 224 225 //dealer finder select subscribe 226 postal.subscribe({ 227 channel: 'com.toyota.tme.t1.dealer', 228 topic: 'dealer.selected', 229 callback: function(data, envelope) { 230 if (data.dealer) { 231 if (data.dealer.id) { 232 dealerId = data.dealer.id; 233 } 234 if (data.dealer.name) { 235 dealerName = data.dealer.name; 236 } 237 if (data.dealer.address._city) { 238 dealerCity = data.dealer.address._city; 239 } 240 if (data.dealer.address.region) { 241 dealerRegion = data.dealer.address.region; 242 } 243 if (data.dealer.address._zip) { 244 dealerZip = data.dealer.address._zip; 245 } 246 } 247 248 taggingDealerDetails(); 249 } 250 }); 251 } else { 252 $submit.eq(1).on('click', dealerSelected); 253 } 254 255 //Summary 256 function triggerSummarySubmit() { 257 T1.channels.statistics.publish(dxp.constants.TOPICS_T1.STATS_TRACK, { 258 extraData: { 259 event: { 260 name: 'formevent', 261 componentName: $formType, 262 componentGroup: 'forms', 263 label: 'summary', 264 action: 'form-step' 265 }, 266 form: { 267 name: $formLabel, 268 step: 'form-summary', 269 conversion: 0 270 }, 271 product: [{ 272 category: 'cars', 273 subCategory: 'new-cars', 274 productInfo: { 275 tmeModelId: modelId, 276 modelName: modelName, 277 } 278 }], 279 dealer: { 280 name: dealerName, 281 dealerId: dealerId, 282 city: dealerCity, 283 zipCode: dealerZip, 284 region: dealerRegion 285 } 286 } 287 }); 288 } 289 $submit.eq(2).on('click', triggerSummarySubmit); 290 291 //triggers on form submit 292 function triggerFormSubmit() { 293 const observer = new MutationObserver(async function(mutations) { 294 for (const mutation of mutations) { 295 if (mutation.attributeName === "class") { 296 const attributeValue = $(mutation.target).prop( 297 mutation.attributeName 298 ); 299 if (attributeValue.includes($validated)) { 300 const userEmailRaw = document.querySelector('.personal-email')?.textContent.trim().toLowerCase(); 301 const userEmail = userEmailRaw && userEmailRaw.includes('@') ? userEmailRaw : ""; 302 const hashEmail = userEmail ? await hashValue(userEmail) : ""; 303 304 T1.channels.statistics.publish( 305 dxp.constants.TOPICS_T1.STATS_TRACK, { 306 extraData: { 307 event: { 308 name: 'formevent', 309 componentName: $formType, 310 componentGroup: 'forms', 311 label: 'form-submit', 312 action: 'form-step' 313 }, 314 form: { 315 name: $formLabel, 316 step: 'form-submit', 317 conversion: 1, 318 }, 319 product: [{ 320 category: 'cars', 321 subCategory: 'new-cars', 322 productInfo: { 323 tmeModelId: modelId, 324 modelName: modelName, 325 } 326 }], 327 dealer: { 328 name: dealerName, 329 dealerId: dealerId, 330 city: dealerCity, 331 zipCode: dealerZip, 332 region: dealerRegion 333 }, 334 ...(hashEmail && { userinfo: { em: hashEmail } }), 335 }, 336 } 337 ); 338 } 339 } 340 } 341 }); 342 observer.observe($submit[0], { 343 attributes: true, 344 }); 345 } 346});
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.