1<!DOCTYPE html> 2<html lang="en-US"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="referrer" content="no-referrer-when-downgrade"/> 7 <meta http-equiv="Content-Language" content="en">
8<script> 9window.daSessionId = function () { 10 try { 11 var match = document.cookie.match(/(?:^|; )da_sid=([0-9a-f]{32})(?:;|$)/); 12 if (match) { 13 return match[1]; 14 } 15 var bytes = new Uint8Array(16), id = '', i; 16 if (window.crypto && window.crypto.getRandomValues) { 17 window.crypto.getRandomValues(bytes); 18 } else { 19 for (i = 0; i < 16; i++) { bytes[i] = Math.floor(Math.random() * 256); } 20 } 21 for (i = 0; i < 16; i++) { id += (bytes[i] < 16 ? '0' : '') + bytes[i].toString(16); } 22 document.cookie = 'da_sid=' + id + '; path=/; SameSite=Lax' + (location.protocol === 'https:' ? '; Secure' : ''); 23 return id; 24 } catch (e) { 25 return ''; 26 } 27}; 28</script>
vendor: 1 bytes, line 28
28
29<script> 30(function () { 31 'use strict'; 32 33 var GOVERN = true; 34 var REAP = true; 35 36 // The partial can now be emitted for the listener reaper alone - in that 37 // case leave MutationObserver untouched. 38 if (!GOVERN && !REAP) { 39 return; 40 } 41 42 var Native = window.MutationObserver; 43 44 if (!Native) { 45 return; 46 } 47 48 /** 49 * Per-origin policy. Origins absent from this map are never touched. 50 * 51 * coalesce - collapse a burst of callbacks into one per animation frame, 52 * passing the accumulated records through. The vendor still 53 * sees real records, just batched. 54 * scopeTo - if the vendor tries to observe document/body/html, point it 55 * at this container instead. Falls back to the original 56 * target when the selector is not on the page. 57 * reap - disconnect this origin's previous observer when it creates 58 * a new one. For vendors that re-register per render and 59 * never clean up. 60 * sentinel - retarget to a shared sentinel node and rely on notify() to 61 * wake them once per render. Only safe for vendors that 62 * rescan the DOM themselves; see notify() below. 63 */ 64 var POLICY = { 65 'plugin.tradepending.com': { coalesce: true, reap: true }, 66 'ver.ev5.ai': { coalesce: true, scopeTo: '#srp-results' }, 67 'cdn.dg.toyota.com': { coalesce: true }, 68 'cdn.userway.org': { coalesce: true } 69 }; 70 71 var newest = {}; // origin -> most recent instance, for reap 72 var governed = []; // every governed instance, for notify() 73 var sentinel = null; 74 75 function sentinelNode() { 76 if (!sentinel) { 77 sentinel = document.createElement('div'); 78 sentinel.id = 'da-observer-sentinel'; 79 sentinel.setAttribute('aria-hidden', 'true'); 80 sentinel.style.display = 'none'; 81 (document.body || document.documentElement).appendChild(sentinel); 82 } 83 return sentinel; 84 } 85 86 function originOf(stack) { 87 var hosts = stack.match(/https?:\/\/([^\/:)\s]+)/g) || []; 88 89 for (var i = 0; i < hosts.length; i++) { 90 var host = hosts[i].replace(/^https?:\/\//, ''); 91 if (POLICY[host]) { 92 return host; 93 } 94 } 95 return null; 96 } 97 98 window.MutationObserver = function (callback) { 99 var origin; 100 101 try { 102 origin = originOf((new Error()).stack || ''); 103 } catch (e) { 104 origin = null; 105 } 106 107 // Not a governed vendor - hand back the real thing and stay out of it. 108 if (!origin) { 109 return new Native(callback); 110 } 111 112 var policy = POLICY[origin]; 113 var pending = []; 114 var queued = false; 115 var instance; 116 117 function flush() { 118 queued = false; 119 var batch = pending; 120 pending = []; 121 122 try { 123 callback.call(instance, batch, instance); 124 } catch (e) { 125 // A vendor throwing is their problem, not ours - never let it 126 // escape into the frame that triggered the mutation. 127 if (window.console && console.debug) { 128 console.debug('[observer-governor] ' + origin + ' callback threw', e); 129 } 130 } 131 } 132 133 function onRecords(records) {
134 // With GOVERN off the vendor gets its records straight through, 135 // unbatched, exactly as the native observer would deliver them. 136 if (!GOVERN || !policy.coalesce) { 137 return callback.call(instance, records, instance); 138 } 139 140 pending = pending.concat(records); 141 142 if (!queued) { 143 queued = true; 144 requestAnimationFrame(flush); 145 } 146 } 147 148 instance = new Native(onRecords); 149 150 var nativeObserve = instance.observe.bind(instance); 151 var nativeDisconnect = instance.disconnect.bind(instance); 152 153 instance.observe = function (target, options) { 154 var finalTarget = target; 155 var isWide = target === document || target === document.body 156 || target === document.documentElement; 157 158 // Retargeting is governing, not reaping. With GOVERN off the vendor 159 // observes exactly what it asked to observe. 160 if (GOVERN && policy.sentinel) { 161 finalTarget = sentinelNode(); 162 options = { attributes: true }; 163 } else if (GOVERN && policy.scopeTo && isWide) { 164 finalTarget = document.querySelector(policy.scopeTo) || target; 165 } 166 167 return nativeObserve(finalTarget, options); 168 }; 169 170 instance.disconnect = function () { 171 pending = []; 172 queued = false; 173 return nativeDisconnect(); 174 }; 175 176 // Reaping is independent of governing: this is the only behaviour that runs 177 // when REAP is on and GOVERN is off. 178 if (REAP && policy.reap && newest[origin]) { 179 try { newest[origin].disconnect(); } catch (e) {} 180 } 181 newest[origin] = instance; 182 183 governed.push({ origin: origin, instance: instance, invoke: onRecords }); 184 185 return instance; 186 }; 187 188 window.MutationObserver.prototype = Native.prototype; 189 190 /** 191 * Tell governed vendors that a render finished, instead of letting them 192 * discover it by watching thousands of nodes change. 193 * 194 * Two mechanisms, because vendors differ: 195 * 196 * 1. The sentinel. Bumping an attribute on a hidden node produces one 197 * genuine, browser-delivered record. Vendors that respond by rescanning 198 * the DOM - which is most of them - work unchanged. Preferred, because 199 * nothing is forged. 200 * 201 * 2. Synthesised records, for vendors that read addedNodes to find new 202 * content and would see nothing from the sentinel. MutationRecord is 203 * not constructible, so these are plain objects; addedNodes is a real 204 * static NodeList off the container so that vendors calling NodeList 205 * methods on it still work. This is a best-effort shim - prefer a 206 * vendor's own documented refresh API where one exists. 207 * 208 * @param {string} containerSelector element that was re-rendered 209 * @param {boolean} synthesize also hand-deliver a childList record 210 */ 211 window.DAObserverGovernor = { 212 notify: function (containerSelector, synthesize) { 213 // Inert when only reaping. Nothing is retargeted to the sentinel in 214 // that mode, and synthesising records would hand vendors notifications 215 // they would never have received natively - which is governing. 216 if (!GOVERN) { 217 return; 218 } 219 220 var node = sentinelNode(); 221 node.setAttribute('data-da-render', String(Date.now())); 222 223 if (!synthesize) { 224 return; 225 } 226 227 var container = document.querySelector(containerSelector); 228 229 if (!container) { 230 return; 231 } 232 233 var record = { 234 type: 'childList', 235 target: container, 236 addedNodes: container.querySelectorAll(':scope > *'), 237 removedNodes: container.querySelectorAll('#da-observer-sentinel'), 238 previousSibling: null, 239 nextSibling: null, 240 attributeName: null, 241 attributeNamespace: null, 242 oldValue: null 243 }; 244 245 governed.forEach(function (entry) { 246 try { entry.invoke([record]); } catch (e) {} 247 }); 248 }, 249 250 // Small surface for checking what is actually being governed at runtime. 251 inspect: function () { 252 return governed.map(function (e) { return e.origin; }); 253 } 254 }; 255})(); 256 257/** 258 * LISTENER REAP - see the header. Its own IIFE because it patches a different 259 * API for a different vendor pathology; it shares nothing with the observer 260 * work above except the stack-origin idea. 261 */ 262(function () { 263 'use strict'; 264 265 var ENABLED = true; 266 267 if (!ENABLED) { 268 return; 269 } 270 271 /** 272 * Matched as substrings of any URL in the constructor stack, so the hashed 273 * build names (dg-inline-save-heart.CFRS092E.min.js) match without pinning 274 * a hash. Add here only after measuring: the vendor must re-bind per render 275 * AND never remove - a vendor that manages its own listeners would fight 276 * this for no gain. 277 */ 278 var REAP_ORIGINS = ['dg-inline-save-heart']; 279 280 var nativeAdd = EventTarget.prototype.addEventListener; 281 var nativeRemove = EventTarget.prototype.removeEventListener; 282 283 var generation = 0; 284 var tracked = []; // { target, type, fn, opts, gen, origin } 285 var reapedTotal = 0; 286 287 // The document's own URL, for excluding inline-script stack frames below. 288 var pageUrl = location.origin + location.pathname; 289 290 function reapOrigin(stack) { 291 var urls = stack.match(/https?:\/\/[^\s)]+/g) || []; 292 293 for (var i = 0; i < urls.length; i++) { 294 // Strip query string and line:column before matching. Without this, 295 // the ?da-listener-reap-origin probe value matches ITSELF in every 296 // inline-script frame - the document URL, probe param included, is 297 // what the stack shows for inline code - and the probe then tracks 298 // every inline listener on the page. Caught by exactly that 299 // happening on the local stack: 230 of the theme's own listeners 300 // reaped in one test run. 301 var clean = urls[i].split('?')[0].replace(/:\d+:\d+\)?$/, ''); 302 303 // Inline frames report the page itself; only external script files 304 // can be a vendor. This also stops a REAP_ORIGINS entry from ever 305 // matching a path segment of the page's own URL. 306 if (clean === pageUrl) { 307 continue; 308 } 309 310 for (var j = 0; j < REAP_ORIGINS.length; j++) { 311 if (clean.indexOf(REAP_ORIGINS[j]) !== -1) { 312 return REAP_ORIGINS[j]; 313 } 314 } 315 } 316 return null; 317 } 318 319 /** 320 * Cheap attribution first: a listener bound synchronously from an external 321 * script names that script in document.currentScript, no stack parse 322 * needed - and script-evaluation time is when a page binds most of its 323 * document-level listeners, ahead of which this patch runs for ALL of 324 * them. Returns the matched origin, null for a definite "external script, 325 * not a tracked vendor" (no stack needed either), or undefined when it 326 * cannot tell - inline script or async callback, where currentScript is 327 * srcless or null - and only that case pays for new Error().stack. 328 */ 329 function currentScriptOrigin() { 330 var el = document.currentScript; 331 332 if (!el || !el.src) { 333 return undefined; 334 } 335 336 var clean = el.src.split('?')[0]; 337 338 for (var j = 0; j < REAP_ORIGINS.length; j++) { 339 if (clean.indexOf(REAP_ORIGINS[j]) !== -1) { 340 return REAP_ORIGINS[j]; 341 } 342 } 343 return null; 344 } 345 346 // Capture is part of a listener's identity to the browser, so it is part 347 // of it here too: {capture: true} and bubble registrations of the same 348 // function are different listeners. 349 function captureOf(opts) { 350 return opts === true || !!(opts && opts.capture); 351 } 352 353 EventTarget.prototype.addEventListener = function (type, fn, opts) { 354 // Document-level targets only: the pathology is the ever-growing 355 // dispatch chain on document/window, not listeners on the cards 356 // themselves - those are garbage-collected with the card. 357 if (this === document || this === window 358 || this === document.body || this === document.documentElement) { 359 var origin = currentScriptOrigin(); 360 361 if (origin === undefined) { 362 try { 363 origin = reapOrigin((new Error()).stack || ''); 364 } catch (e) { 365 origin = null; 366 } 367 } 368 369 if (origin && typeof fn === 'function') { 370 tracked.push({ target: this, type: type, fn: fn, opts: opts, gen: generation, origin: origin }); 371 } 372 } 373 return nativeAdd.call(this, type, fn, opts); 374 }; 375 376 // Vendors removing their own listeners must keep working exactly as before; 377 // drop our record so a later reap does not double-remove. The scan is 378 // gated to the four tracked targets with records present - Swiper's 379 // per-render detachEvents used to walk it for every element it touched - 380 // and matches capture, since splicing the capture record while a vendor 381 // removed its bubble twin would leave a live listener untracked forever. 382 EventTarget.prototype.removeEventListener = function (type, fn, opts) { 383 if (tracked.length !== 0 384 && (this === document || this === window 385 || this === document.body || this === document.documentElement)) { 386 for (var i = tracked.length - 1; i >= 0; i--) { 387 var t = tracked[i]; 388 if (t.target === this && t.type === type && t.fn === fn 389 && captureOf(t.opts) === captureOf(opts)) { 390 tracked.splice(i, 1); 391 break; 392 } 393 } 394 } 395 return nativeRemove.call(this, type, fn, opts); 396 }; 397 398 window.DAListenerReaper = { 399 /** 400 * Called by the theme when an SRP render settles. Keeps the newest TWO 401 * generations - the render on screen plus one back, which covers 402 * handlers a vendor adds asynchronously after its render hook fired - 403 * and removes everything older through the native removeEventListener, 404 * with the exact arguments the vendor used. 405 * 406 * Age alone is not staleness, and TWO conditions guard a removal. 407 * 408 * Generation 0 is never reaped, full stop. advance() runs at the top 409 * of the theme's settled-render handler, before the vendor is handed 410 * that render's cards, so generation 0 is what was bound before any 411 * search render completed - page-init listeners, including the 412 * delegated singleton a vendor binds once at script evaluation and 413 * never rebinds. The plain age rule removed that permanently on the 414 * shopper's second search, and the synthetic test leaker could not 415 * catch it because it has no init-time singleton. The cost of the 416 * blanket keep is that anything a vendor bound during the very first 417 * render is kept too: one render's worth of listeners held for the 418 * life of the page, against unbounded growth, which is the trade this 419 * whole mechanism exists to make. 420 * 421 * Beyond that, a record goes only when the SAME origin has bound the 422 * SAME event type in a LATER generation - the rebind that replaced 423 * it, which is the "re-binds per render" premise demanded as evidence 424 * rather than assumed. Origin+type is not listener identity and does 425 * not claim to be: a singleton bound mid-session, of the same type as 426 * a per-render batch from the same script, would still be matched by 427 * its neighbours' rebind. Generation 0 covers the case that has 428 * actually been observed in the wild; this covers the rest. 429 */ 430 advance: function () { 431 generation++; 432 433 var newestGen = {}; 434 var keep = []; 435 var i, key; 436 437 for (i = 0; i < tracked.length; i++) { 438 key = tracked[i].origin + '|' + tracked[i].type; 439 if (!(key in newestGen) || tracked[i].gen > newestGen[key]) { 440 newestGen[key] = tracked[i].gen; 441 } 442 } 443 444 for (i = 0; i < tracked.length; i++) { 445 var t = tracked[i]; 446 447 if (t.gen === 0) { 448 keep.push(t); 449 continue; 450 } 451 452 if (t.gen <= generation - 2 && newestGen[t.origin + '|' + t.type] > t.gen) { 453 try { nativeRemove.call(t.target, t.type, t.fn, t.opts); } catch (e) {} 454 reapedTotal++; 455 } else { 456 keep.push(t); 457 } 458 } 459 460 tracked = keep; 461 }, 462 463 stats: function () { 464 return { generation: generation, live: tracked.length, reaped: reapedTotal, origins: REAP_ORIGINS.slice() }; 465 } 466 }; 467})(); 468</script>
468 469<link rel="icon" href="https://bucket.dealervenom.com/assets/oem/toyota/favicon/toyota-red-favicon.ico?auto=compres&format&ixlib=php-1.2.1&width=16&w=32" sizes="32x32"><link rel="apple-touch-icon" href="https://bucket.dealervenom.com/assets/oem/toyota/favicon/toyota-red-favicon.ico?auto=compres&format&ixlib=php-1.2.1&width=16&w=180"> <meta name="viewport" content="width=device-width, initial-scale=1"> 470 <meta name="google-site-verification" content="S66h9gmPYZ8M8TV8Miq45RED9QtLVSqz_rDKTiL7nh4"/> 471 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/jquery.min.js?v=1.537.43" as="script"> 472 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/globalJs.js?v=1.789.534" as="script"> 473 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-events.js?v=1.789.527" as="script"> 474 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/webfonts/fa-light-300.subset.woff2" as="font" type="font/woff2" crossorigin> 475 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/webfonts/fa-solid-900.subset.woff2" as="font" type="font/woff2" crossorigin> 476 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/webfonts/fa-brands-400.subset.woff2" as="font" type="font/woff2" crossorigin> 477 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/webfonts/fa-duotone-900.subset.woff2" as="font" type="font/woff2" crossorigin> 478
478<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/jquery.min.js?v=1.537.43"></script>
478 479
479<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/globalJs.js?v=1.789.534"></script>
479 480
480<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-events.js?v=1.789.527"></script>
480 481 <!-- DV Google Tag Manager --> 482
482<script>
vendor: 555 bytes, lines 482-496
482 483 (function (w, d, s, l, i) { 484 w[l] = w[l] || []; 485 w[l].push({ 486 'gtm.start': new Date().getTime(), 487 event: 'gtm.js' 488 }); 489 var f = d.getElementsByTagName(s)[0], 490 j = d.createElement(s), 491 dl = l != 'dataLayer' ? '&l=' + l : ''; 492 j.async = true; 493 j.src = 494 'https://www.googletagmanager.com/gtm.js?id=' + i + dl; 495 f.parentNode.insertBefore(j, f); 496 })(window, document, 'script', 'dataLayer', '
496GTM-5CPFDTJM
vendor: 8 bytes, lines 496-497
496'); 497
497</script>
497 498 <!-- DV End Google Tag Manager -->
vendor: 72 bytes, lines 498-499
498 499 <script async src="https://www.googletagmanager.com/gtag/js?id=
499G-32FXJLL18G
vendor: 16 bytes, lines 499-500
499"></script> 500
500<script> 501
vendor: 184 bytes, lines 501-508
501window.dataLayer = window.dataLayer || []; 502 503 function gtag() { 504 dataLayer.push(arguments); 505 } 506 507 gtag('js', new Date()); 508 gtag('config', '
508G-32FXJLL18G
vendor: 20 bytes, lines 508-509
508'); 509
509gtag('config', 'G-M3B4B59Q4Z'); 510 </script>
510 511
511<script> 512 console.log("Enabling SD Analytics..."); 513 (function (s, h, i, f, t, d, g, l) { 514 s[d] = s[d] || function () { 515 (s[d].q = s[d].q || []).push(arguments) 516 }, s[d].l = 1 * new Date(); g = h.createElement(i), 517 l = h.getElementsByTagName(i)[0]; g.async = 1; g.src = f + 518 '?containerId=' + t + '&dl=' + d; l.parentNode.insertBefore(g, l) 519 })(window, document, 'script', 'https://toyota-tagging-prod.azureedge.net/scripts/sd.js', 'Toyota', 'sd'); 520 sd('create', 'TOYOTA', '32136', 'DEALERVENOM'); 521 sd('dataLayer', { 522 pageType: 'Vehicle Listing', 523 websiteTier: 'Tier 3', 524 pageBrand: 'Toyota', 525 sessionId: (window.daSessionId ? window.daSessionId() : ''), 526 language: 'en', //note(ethan): need to change this to allow translations 527 trafficType: 'Organic Search', 528 dealerZipCode: '27896', 529 dealerState: 'NC', 530 dealerCity: 'Wilson', 531 dealerName: '', 532 dealerTda: 'SET10', 533 siteTechnologyVersion: '2.0031', 534 userZipCode: '', //note(ethan): add user location 535 userCity: '', 536 userState: '' 537 }); 538 sd('send', 'pageview'); 539 540 if (window.location.href.includes("thank-you")) { 541 var urlSearch = new URLSearchParams(window.location.search); 542 var tradeInYear = urlSearch.get("year") || urlSearch.get("yr"); 543 var tradeInMake = urlSearch.get("make"); 544 var tradeInModel = urlSearch.get("model"); 545 var formTitle = urlSearch.get("title") || ""; 546 547 function sendThankYouFormSubmission(displayType, formVehicle, tradeIn) { 548 var payload = { 549 leadId: urlSearch.get("leadid"), 550 formType: getSDFormType(formTitle.replace("+", "")), 551 leadType: 'lead', 552 displayType: displayType, 553 events: 'formSubmission' 554 }; 555 556 if (formVehicle) { 557 payload.formVehicle = formVehicle; 558 } 559 560 if (tradeIn) { 561 payload.tradeIn = tradeIn; 562 } 563 564 sd('dataLayer', payload); 565 sd('send'); 566 } 567 568 function getThankYouTradeIn() { 569 if (!tradeInYear || !tradeInMake || !tradeInModel) { 570 return null; 571 } 572 573 return { 574 year: tradeInYear, 575 make: tradeInMake, 576 model: tradeInModel 577 }; 578 } 579 580 function requestThankYouVehicleDetails(displayType, tradeIn) { 581 $.post("/app/themes/dv-framework/ajax/sdformvehicle.php", { 582 vin: urlSearch.get("vin") 583 }).done(function (data) { 584 var parsedVehicle = null; 585 586 try { 587 parsedVehicle = JSON.parse(data); 588 } catch (error) { 589 parsedVehicle = null; 590 } 591 592 sendThankYouFormSubmission(displayType, parsedVehicle, tradeIn); 593 }).fail(function () { 594 sendThankYouFormSubmission(displayType, null, tradeIn); 595 }); 596 } 597 598 if (urlSearch.get("vin") && tradeInYear && tradeInMake && tradeInModel) { 599 requestThankYouVehicleDetails('modal', getThankYouTradeIn()); 600 } else if (urlSearch.get("vin")) { 601 requestThankYouVehicleDetails('modal', null); 602 } else if (tradeInYear && tradeInMake && tradeInModel) { 603 sendThankYouFormSubmission('in-page', null, getThankYouTradeIn()); 604 } else { 605 sendThankYouFormSubmission('in-page', null, null); 606 } 607 } else { 608 console.log("NO THANK YOU..."); 609 } 610 611 //carousel clicks sd click 612 document.addEventListener('click', function (event) { 613 var target = event.target; 614 while (target && target !== document) { 615 if (target.classList && target.classList.contains('post-dv-offers')) { 616 var assetName = target.querySelector('a').getAttribute('title'); 617 var assetPosition = target.getAttribute('data-slick-index'); 618 sd('dataLayer', { 619 events: 'carouselClick', 620 assetName: assetName, 621 assetPosition: assetPosition 622 }); 623 sd('send'); 624 break; 625 } 626 target = target.parentNode; 627 } 628 }); 629 630 </script>
630 631 632 633 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/srpCSS/algolia.css?v=1.790.370" as="style"> 634 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/srpCSS/algolia.css?v=1.790.370"> 635 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/avgrund/avgrund.css?v=1.598.642" as="style"> 636 <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.25/jquery.fancybox.min.css" as="style"> 637 <!--<link rel="preload" href="https://code.jquery.com/jquery-migrate-3.4.1.min.js" as="script">--> 638 <link rel="preload" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.25/jquery.fancybox.min.js" as="script"> 639 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/avgrund/avgrund.css?v=1.598.642"> 640 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.25/jquery.fancybox.min.css"/> 641 <!--
641<script type="text/javascript" src="https://code.jquery.com/jquery-migrate-3.4.1.min.js"></script>
641--> 642
642<script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.1.25/jquery.fancybox.min.js"></script>
642 643 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/srpCSS/algolia-grid.css?v=1.763.753"> 644 645 646 647 648 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/footer.css?v=1.741.129" as="style"> 649 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/slick/slick.css?v=1.536.957" as="style"> 650 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/slick/slick-theme.css?v=1.536.959" as="style"> 651 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/footer.css?v=1.741.129"> 652 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/slick/slick.css?v=1.536.957"> 653 <link rel="stylesheet" type="text/css" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/slick/slick-theme.css?v=1.536.959"> 654 <!-- Redux Styling Below --> 655 656 <style> 657 header { 658 height: 75px !important; 659 } 660 661 .srp_cta:hover { 662 background-color: #000000; 663 } 664 665 .ginput_container_textarea textarea:hover { 666 border-color: #eb0a1e !important; 667 } 668 669 .primary_color, 670 .dv_button { 671 color: #eb0a1e; 672 } 673 674 .dv_button { 675 border-left: 10px solid#000000; 676 } 677 678 body .btn.dds-search { 679 background-color: #eb0a1e; 680 } 681 682 button, 683 .dv-button { 684 background: #eb0a1e; 685 color: #ffffff; 686 } 687 688 button:hover, 689 .dv-button:hover { 690 background: #000000; 691 } 692 693 .primary_background_color, 694 .gform_footer input.button, 695 .gform_page_footer input.button { 696 background-color: #eb0a1e; 697 } 698 699 .dv_button_reverse { 700 color: #eb0a1e; 701 } 702 703 .vdp-roadster-express { 704 background-color: #063497; 705 color: #ffffff !important; 706 border: 1px solid#ffcc00; 707 } 708 709 .vdp-roadster-express:hover { 710 background-color: #ffcc00; 711 color: #063497 !important; 712 border: 1px solid#063497; 713 } 714 715 .srp-roadster-express { 716 background-color: #063497; 717 color: #ffffff; 718 } 719 720 .srp-roadster-express:hover { 721 background-color: #ffcc00; 722 } 723 724 .vdp-content .award-honor, 725 .new-used, 726 .incentive-items h4, 727 .warranty-font-size-two, 728 .total-savings, 729 .map_title_bottom { 730 color: #eb0a1e; 731 } 732 733 .google-box-container-left-bottom, 734 .box-three-container, 735 .box-three-container-class { 736 background-color: #eb0a1e !important; 737 } 738 739 .google-circle { 740 background-color: #000000; 741 } 742 743 .secondary_color, 744 .map_title_top { 745 color: #000000; 746 } 747 748 .secondary_background_color {
749 background-color: #000000; 750 } 751 752 .srp_main .block-nav li { 753 background-color: #eb0a1e; 754 } 755 756 .dropbtn { 757 background-color: #eb0a1e !important; 758 color: #fff; 759 } 760 761 .gform_wrapper input:hover, 762 .ginput_container_select select:hover, 763 .address_state select:hover { 764 border-color: #eb0a1e !important; 765 } 766 767 .gform_footer input.button { 768 border: 0 !important; 769 } 770 771 .gform_footer input.button:hover { 772 border: 0 !important; 773 } 774 775 .gform_wrapper input[type=checkbox]:checked + label:before, 776 .gform_wrapper input[type=radio]:checked + label:before { 777 background-color: #eb0a1e !important; 778 } 779 780 #mobile-nav-subheader { 781 top: 75px; 782 background: #eb0a1e; 783 } 784 785 .brand-weight:hover { 786 color: #eb0a1e; 787 } 788 789 .sub-header, 790 .subheader, 791 .search-box { 792 top: 75px; 793 } 794 795 .customize-support .sub-header, 796 .customize-support .subheader { 797 top: calc(75px +32px); 798 } 799 800 .dv-sidenav { 801 background-color: #eb0a1e !important; 802 top: 75px !important; 803 height: calc(100vh - 75px); 804 } 805 806 .wpb_column a { 807 color: #eb0a1e; 808 } 809 810 .not-found-button > a:hover { 811 color: #eb0a1e !important; 812 } 813 814 815 .internal-btn button { 816 background-color: #eb0a1e !important; 817 color: #ffffff !important; 818 } 819 820 .internal-btn button:hover { 821 background-color: #000000 !important; 822 color: #ffffff !important; 823 } 824 825 .internal-btn a { 826 background-color: #eb0a1e !important; 827 color: #ffffff !important; 828 } 829 830 .internal-btn a:hover { 831 background-color: #000000 !important; 832 color: #ffffff !important; 833 } 834 835 .internal-header { 836 background: linear-gradient(rgba(32,30,30,0.99),rgba(32,30,30,0.99)); 837 } 838 839 @media screen and (max-width: 1335px) { 840 header { 841 height: 75px !important; 842 } 843 844 .sub-header, 845 .subheader { 846 top: 75px !important; 847 } 848 849 .customize-support .sub-header, 850 .customize-support .subheader { 851 top: calc(75px +86px) !important; 852 } 853 854 .customize-support .dv-sidenav { 855 top: calc(75px +86px) !important; 856 } 857 858 .customize-support #mobile-nav-subheader { 859 top: calc(75px +46px) !important; 860 } 861 862 #mobile-nav-subheader { 863 top: 75px !important; 864 } 865 866 .dv-sidenav { 867 top: 75px !important; 868 height: calc(100vh - 75px); 869 } 870 } 871 </style> 872 873 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-hydrate.js?v=1.772.37" as="script"> 874
874<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-hydrate.js?v=1.772.37"></script>
874 875 876 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-modal-disclaimer.js?v=1.774.900" as="script"> 877
877<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/dv-modal-disclaimer.js?v=1.774.900"></script>
877 878 879 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-gform-loader.js?v=1.786.483" as="script"> 880
880<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-gform-loader.js?v=1.786.483"></script>
880 881 882 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-modal.js?v=1.790.314" as="script"> 883
883<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-modal.js?v=1.790.314"></script>
883 884 885 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-flyout.js?v=1.791.267" as="script"> 886
886<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/da-flyout.js?v=1.791.267"></script>
886 887 888 <link rel="preload" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" as="style"> 889 <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css"/> 890 891 <link rel="preload" as="script" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"> 892
892<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
892 893 894 <link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/slick.min.js?v=1.536.999" as="script"> 895
895<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/slick.min.js?v=1.536.999"></script>
895 896 897
897<script> 898 $(document).ready(function () { 899 $('body').addClass('dv-logged-out'); 900 }); 901 </script>
901 902 903 <style> 904 :root { 905 --primary-color: #eb0a1e; 906 --secondary-color: #000000; 907 --mobile-break-point: 1335px; 908 --header-height: 75px; 909 --mobile-header-height: 75px; 910 --header-design-background-color: #ffffff; 911 --header-design-text-color: #000000; 912 --header-design-border-color: #555555; 913 --menu-design-background-color: #ffffff; 914 --menu-design-text-color: #000000; 915 --menu-design-text-hover-color: #ffffff; 916 --menu-design-background-hover-color: #eb0a1e; 917 --brand-button-color: #eb0a1e; 918 --brand-title-color: #ffffff; 919 --brand-button-hover-color: #000000; 920 --brand-title-hover-color: #ffffff; 921 --swiper-theme-color: var(--primary-color); 922 } 923 </style> 924
925<script> 926 const _COOKIENAME = "dv_alertbar"; 927 </script>
927<div class="dv-alertbar"> 928 <div class="dv-alertbar-content"> 929 <p><a href="/new-vehicles/?make=Toyota&model=Tacoma&model=Tacoma%20i-FORCE%20MAX"><img class="dv-desktop-alert dv-alert-img aligncenter" src="https://s3.amazonaws.com/cdn.dealervenom.com/hubert-vester-toyota/M10-Tacoma.png?auto=compress%2Cformat&ixlib=php-3.3.1" alt="Buy 3 Tires, Get the 4th for $1" /></a></p> 930<style>html.alertbar-active{scroll-snap-type:none!important;overflow:auto!important}.dv-alert-img{display:block;max-width:100%!important;height:auto!important;margin:0 auto}@media (max-width:767px){.dv-alert-img{width:100%!important}.dv-alertbar a{display:block;line-height:0}}</style> 931<p>
931<script> 932if ('scrollRestoration' in history) history.scrollRestoration = 'manual';</p> 933<p>const handleAlertBar = () => { 934 if (document.querySelector('.dv-alertbar')) { 935 document.documentElement.classList.add('alertbar-active'); 936 window.scrollTo(0, 0); 937 } 938};</p> 939<p>document.addEventListener('DOMContentLoaded', handleAlertBar); 940window.addEventListener('load', handleAlertBar);</p> 941<p>window.closeAlertbar = (original => function() { 942 if (typeof original === 'function') original(); 943 document.documentElement.classList.remove('alertbar-active'); 944})(window.closeAlertbar); 945</script>
945</p> 946 947 </div> 948 <div class="dv-alertbar-close"> 949 <i class="fas fa-times" onclick="closeAlertbar();" aria-label="Close"></i> 950 </div> 951 </div>
951<script> 952 window.addEventListener("DOMContentLoaded", function(event) { 953 window.addEventListener("scroll", function(ev) { 954 var header = document.querySelector("header"); 955 var headerHeight = header.getBoundingClientRect().height; 956 var distanceToTop = header.getBoundingClientRect().top; 957 var fwSearch = document.querySelector(".dv-fw-search"); 958 fwSearch.style.top = "".concat(distanceToTop + headerHeight, "px"); 959 }); 960 }); 961 962 var shown = sessionStorage.getItem(_COOKIENAME); 963 if (shown != null) { 964 document.querySelector(".dv-alertbar").remove(); 965 } 966 function closeAlertbar() { 967 if (shown == null) { 968 sessionStorage.setItem(_COOKIENAME, true); 969 } 970 var v = document.querySelector(".dv-alertbar"); 971 var x = document.querySelector(".dv-alertbar-content"); 972 var z = document.querySelector(".dv-fw-search"); 973 var h = x.getBoundingClientRect().height; 974 var j = z.getBoundingClientRect().height; 975 var k = z.getBoundingClientRect().top; 976 z.style.height = "".concat(j + 75, "px"); 977 z.style.top = "".concat(k - 75, "px"); 978 x.style.height = "".concat(h, "px"); 979 v.classList.add("close"); 980 } 981 982 window.sessionStorage; 983 </script>
983 984 <style> 985 .dv-alertbar { 986 background: #eb0a1e; 987 display: -webkit-box; 988 display: -ms-flexbox; 989 display: flex; 990 -ms-flex-wrap: nowrap; 991 flex-wrap: nowrap; 992 -webkit-box-align: center; 993 -ms-flex-align: center; 994 align-items: center; 995 margin: 0; 996 height: auto; 997 -webkit-transition: all 200ms ease-in-out; 998 -o-transition: all 200ms ease-in-out; 999 transition: all 200ms ease-in-out; 1000 position: relative; 1001 z-index: 7; 1002 } 1003 .dv-alertbar.close { 1004 height: 0; 1005 visibility: hidden; 1006 opacity: 0; 1007 } 1008 .dv-alertbar * { 1009 box-sizing: border-box; 1010 } 1011 .dv-alertbar .dv-alertbar-content { 1012 color: #fff; 1013 font-size: 18px; 1014 flex: 1 1 90%; 1015 width: 90%; 1016 padding: 25px 50px; 1017 } 1018 .dv-alertbar .dv-alertbar-content p, 1019 .dv-alertbar .dv-alertbar-content span, 1020 .dv-alertbar .dv-alertbar-content div { 1021 line-height: 1 1022 } 1023 .dv-alertbar .dv-alertbar-close { 1024 text-align: right; 1025 flex: 1; 1026 width: auto; 1027 } 1028 .dv-alertbar .dv-alertbar-close i { 1029 font-size: 24px; 1030 color: #000000; 1031 padding: 25px; 1032 display: inline-block; 1033 transition: all 200ms ease-in-out; 1034 /* position: absolute; 1035 right: 0; 1036 top: 0; 1037 z-index: 0; */ 1038 } 1039 .dv-alertbar .dv-alertbar-close i:hover { 1040 color: #000000; 1041 cursor: pointer; 1042 } 1043 @media screen and (max-width: 768px) { 1044 .dv-alertbar .dv-alertbar-content { 1045 padding: 12.5px 25px 1046 } 1047 } 1048 </style>
1048<script> 1049 sessionStorage.removeItem("dv-global-modal"); 1050 window.sessionStorage; 1051 </script>
1051<!-- This site is running CAOS: Complete Analytics Optimization Suite for Wordpress -->
1051<script> 1052 (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 1053 (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 1054 m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 1055 })(window,document,'script','https://www.hubertvestertoyota.com/app/plugins/dv-google-analytics-utm/cache/local-ga.js','ga');ga('create', '', 'auto');ga('send', 'pageview');</script>
1055<title>Shop New Vehicles in Wilson, NC | Hubert Vester Toyota</title> 1056<meta name='robots' content='max-image-preview:large' /> 1057 1058<!-- Start Dealer Alchemist - Premium SEO by: Dealer Alchemist --> 1059<meta name="robots" content="noydir" /> 1060<meta name="description" content="No hassle. Real prices online – buy your new car today! Exclusive cars deals. Real-time pricing. Buy with confidence. Save up to thousands. No-hassle car buying. We have the area’s largest selection of Toyota new vehicles at Hubert Vester Toyota. Visit us now in Wilson, NC!" /> 1061<meta property="og:image" content="" /> 1062<meta property="og:locale" content="en_US" /> 1063<meta property="og:type" content="website" /> 1064<meta property="og:title" content="Shop New Vehicles in Wilson, NC | Hubert Vester Toyota" /> 1065<meta property="og:description" content="No hassle. Real prices online – buy your new car today! Exclusive cars deals. Real-time pricing. Buy with confidence. Save up to thousands. No-hassle car buying. We have the area’s largest selection of Toyota new vehicles at Hubert Vester Toyota. Visit us now in Wilson, NC!" /> 1066<meta property="og:url" content="https://www.hubertvestertoyota.com/new-vehicles/" /> 1067<meta property="og:site_name" content="Hubert Vester Toyota" /> 1068<meta name="twitter:card" content="summary" /> 1069<meta name="twitter:site" content="@HVToyota" /> 1070<meta name="twitter:title" content="Shop New Vehicles in Wilson, NC | Hubert Vester Toyota" /> 1071<meta name="twitter:description" content="No hassle. Real prices online – buy your new car today! Exclusive cars deals. Real-time pricing. Buy with confidence. Save up to thousands. No-hassle car buying. We have the area’s largest selection of Toyota new vehicles at Hubert Vester Toyota. Visit us now in Wilson, NC!" /> 1072<!-- End Dealer Alchemist - Premium SEO by: Dealer Alchemist | 0.00226s --> 1073 1074<link rel='dns-prefetch' href='//s.w.org' /> 1075<link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='dv-team-members' href='https://www.hubertvestertoyota.com/app/plugins/dv-meet-the-team/assets/css/meet-the-team.css?ver=5.9.5' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='wp-block-library' href='https://www.hubertvestertoyota.com/wp/wp-includes/css/dist/block-library/style.min.css?ver=5.9.5' type='text/css' media='all' /><style id='global-styles-inline-css' type='text/css'> 1076body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);
1076--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--duotone--dark-grayscale: url('#wp-duotone-dark-grayscale');--wp--preset--duotone--grayscale: url('#wp-duotone-grayscale');--wp--preset--duotone--purple-yellow: url('#wp-duotone-purple-yellow');--wp--preset--duotone--blue-red: url('#wp-duotone-blue-red');--wp--preset--duotone--midnight: url('#wp-duotone-midnight');--wp--preset--duotone--magenta-yellow: url('#wp-duotone-magenta-yellow');--wp--preset--duotone--purple-green: url('#wp-duotone-purple-green');--wp--preset--duotone--blue-orange: url('#wp-duotone-blue-orange');--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}
1076.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;} 1077</style> 1078<link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='auth0-widget' href='https://www.hubertvestertoyota.com/app/plugins/auth0/assets/css/main.css?ver=5.9.5' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='menu-image' href='https://www.hubertvestertoyota.com/app/plugins/dv-menu-image/menu-image.css?ver=1.1' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='dv-offers-styles' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/dv-offers/dv-offers.css?ver=1.791.294' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='globalStyle' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/globalStyle.css?ver=1.785.865' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='dv-modal-styles' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/dv-modal/dv-modal.css?ver=1.790.321' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='ag-modal-form-styles' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/ag-modal-form/ag-modal-form.css?ver=1.701.907' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='vehicle-models-menu' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/vehicle-models-menu/vehicle-models-menu.css?ver=1.738.884' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='style' href='https://www.hubertvestertoyota.com/app/themes/dv-hubert-vester-toyota/style.css?ver=1.776.842' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='fontawesome' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/css/all.min.css?ver=1.694.28' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='fontawesome-subset' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/fontawesome/css/fa-subset.css?ver=1.785.828' type='text/css' media='all' /><link rel="https://api.w.org/" href="https://www.hubertvestertoyota.com/wp-json/" /><link rel="alternate" type="application/json" href="https://www.hubertvestertoyota.com/wp-json/wp/v2/pages/16" /><link rel="EditURI" type="application/rsd+xml" title="RSD" href="https://www.hubertvestertoyota.com/wp/xmlrpc.php?rsd" /> 1079<link rel="wlwmanifest" type="application/wlwmanifest+xml" href="https://www.hubertvestertoyota.com/wp/wp-includes/wlwmanifest.xml" /> 1080<link rel="alternate" type="application/json+oembed" href="https://www.hubertvestertoyota.com/w
1080p-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.hubertvestertoyota.com%2Fnew-vehicles%2F" /> 1081<link rel="alternate" type="text/xml+oembed" href="https://www.hubertvestertoyota.com/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fwww.hubertvestertoyota.com%2Fnew-vehicles%2F&format=xml" /> 1082 <!-- Stream WordPress user activity plugin v3.6.0 --> 1083<noscript><style>.vce-row-container .vcv-lozad {display: none}</style></noscript><meta name="generator" content="Powered by Visual Composer Website Builder - fast and easy-to-use drag and drop visual editor for WordPress."/><!-- HFCM by 99 Robots - Snippet # 7: QoreAi -->
1084<script data-integrator-id="c98bf908ed7a44b78ab0276031c1cbd1" id="_kzsc" src="https://app.qoreai.com/cs/qoreai.js"></script>
1084 1085<!-- /end HFCM by 99 Robots --> 1086<!-- HFCM by 99 Robots - Snippet # 3: ComplyAuto Header Script -->
1087<script src="https://cdn.complyauto.com/cookiebanner/banner/43a2cf52-cba9-449b-b369-96150e045d6a/blocker.js"></script>
1087 1088<!-- /end HFCM by 99 Robots --> 1089 <style type="text/css" id="wp-custom-css"> 1090 img[src*="HV-Toyota-Black"] { 1091 max-height: 60px !important; 1092 max-width: 220px !important; 1093 width: auto !important; 1094 height: auto !important; 1095 object-fit: contain !important; 1096} </style> 1097 <style type="text/css">#wpadminbar, #wpadminbar .menupop .ab-sub-wrapper, .ab-sub-secondary, #wpadminbar .quicklinks .menupop ul.ab-sub-secondary,#wpadminbar .quicklinks .menupop ul.ab-sub-secondary .ab-submenu {background:#2a2e35}#wpadminbar a.ab-item, #wpadminbar>#wp-toolbar span.ab-label, #wpadminbar>#wp-toolbar span.noticon, #wpadminbar .ab-icon:before,#wpadminbar .ab-item:before {color:#b7bbcc}#wpadminbar .quicklinks .menupop ul li a, #wpadminbar .quicklinks .menupop ul li a strong, #wpadminbar .quicklinks .menupop.hover ul li a,#wpadminbar.nojs .quicklinks .menupop:hover ul li a {color:#b7bbcc; font-size:13px !important }#wpadminbar .ab-top-menu>li.hover>.ab-item,#wpadminbar.nojq .quicklinks .ab-top-menu>li>.ab-item:focus,#wpadminbar:not(.mobile) .ab-top-menu>li:hover>.ab-item,#wpadminbar:not(.mobile) .ab-top-menu>li>.ab-item:focus{background:#2a2e35; color:#ffffff}#wpadminbar:not(.mobile)>#wp-toolbar a:focus span.ab-label,#wpadminbar:not(.mobile)>#wp-toolbar li:hover span.ab-label,#wpadminbar>#wp-toolbar li.hover span.ab-label, #wpadminbar.mobile .quicklinks .hover .ab-icon:before,#wpadminbar.mobile .quicklinks .hover .ab-item:before, #wpadminbar .quicklinks .menupop .ab-sub-secondary>li .ab-item:focus a,#wpadminbar .quicklinks .menupop .ab-sub-secondary>li>a:hover {color:#ffffff}#wpadminbar .quicklinks .ab-sub-wrapper .menupop.hover>a,#wpadminbar .quicklinks .menupop ul li a:focus,#wpadminbar .quicklinks .menupop ul li a:focus strong,#wpadminbar .quicklinks .menupop ul li a:hover,#wpadminbar .quicklinks .menupop ul li a:hover strong,#wpadminbar .quicklinks .menupop.hover ul li a:focus,#wpadminbar .quicklinks .menupop.hover ul li a:hover,#wpadminbar li #adminbarsearch.adminbar-focused:before,#wpadminbar li .ab-item:focus:before,#wpadminbar li a:focus .ab-icon:before,#wpadminbar li.hover .ab-icon:before,#wpadminbar li.hover .ab-item:before,#wpadminbar li:hover #adminbarsearch:before,#wpadminbar li:hover .ab-icon:before,#wpadminbar li:hover .ab-item:before,#wpadminbar.nojs .quicklinks .menupop:hover ul li a:focus,#wpadminbar.nojs .quicklinks .menupop:hover ul li a:hover, #wpadminbar .quicklinks .ab-sub-wrapper .menupop.hover>a .blavatar,#wpadminbar .quicklinks li a:focus .blavatar,#wpadminbar .quicklinks li a:hover .blavatar{color:#ffffff}#wpadminbar .menupop .ab-sub-wrapper, #wpadminbar .shortlink-input {background:#2a2e35}#wpadminbar .ab-submenu .ab-item, #wpadminbar .quicklinks .menupop ul.ab-submenu li a,#wpadminbar .quicklinks .menupop ul.ab-submenu li a.ab-item {color:#ffffff}#wpadminbar .ab-submenu .ab-item:hover, #wpadminbar .quicklinks .menupop ul.ab-submenu li a:hover,#wpadminbar .quicklinks .menupop ul.ab-submenu li a.ab-item:hover {color:#b7bbcc}.quicklinks li.wpshapere_site_title a{ outline:none; border:none;}.quicklinks li.wpshapere_site_title {width:180px !important;margin-top:3px !important;}.quicklinks li.wpshapere_site_title a{outline:none; border:none;}.quicklinks li.wpshapere_site_title a, .quicklinks li.wpshapere_site_title a:hover, .quicklinks li.wpshapere_site_title a:focus {background:url(https://bucket.dealervenom.com/assets/autogo/logos/AutoGO-Logo-White-XL.png?auto=compress%2Cformat&ixlib=php-1.2.1&w=400) 15px 3px no-repeat !important; text-indent:-9999px !important; width:auto;background-size:50%!important;}</style> 1098 <link rel="canonical" href="https://www.hubertvestertoyota.com/new-vehicles/?model=Tacoma%20i-FORCE%20MAX" /> 1099 1100</head> 1101 1102<body class="srp_main"> 1103 <style> 1104 header { 1105 background: #ffffff } 1106 1107 header, 1108 header .ag-brand-logo, 1109 header .ag-dealer-logo, 1110 header .ag-dealer-info { 1111 border-color: #555555 } 1112 1113 header .ag-dealer-info a, 1114 header .ag-dealer-nav #main_nav_menu #menu-main-nav-menu>li>a { 1115 color: #000000 !important 1116 } 1117 1118 header .ag-dealer-nav #main_nav_menu #menu-main-nav-menu>li>ul a { 1119 color: #000000 !important 1120 } 1121 1122 header .ag-dealer-nav #main_nav_menu #menu-main-nav-menu>li>ul>li.dv-submenu-model-selector .dv-submenu-dealer-models p a { 1123 color: #fff !important 1124 } 1125 1126 header .ag-dealer-nav #main_nav_menu #menu-main-nav-menu>li>ul a:hover { 1127 color: #ffffff !important 1128 } 1129 1130 header #menu-main-nav-menu li.has-sub ul { 1131 background-color: #ffffff !important; 1132 } 1133 1134 header #menu-main-nav-menu li.has-sub ul a:hover { 1135 background-color: #eb0a1e !important; 1136 color: #ffffff !important 1137 } 1138 1139 @media screen and (max-width: 1335px) { 1140 header .ag-dealer-info { 1141 border-right: 1px solid var(--header-design-border-color) 1142 } 1143 1144 header .ag-dealer-nav { 1145 display: none 1146 } 1147 1148 header .ag-dealer-logo { 1149 margin-right: auto 1150 } 1151 } 1152</style> 1153<style> 1154 .ag-top-nav { 1155 padding: 12.5px 25px; 1156 background: #000000; 1157 display: flex; 1158 display: -webkit-flex; 1159 display: -ms-flexbox; 1160 flex-flow: row nowrap; 1161 align-items: center; 1162 justify-content: flex-end; 1163 position: sticky; 1164 top: 0; 1165 z-index: 150; 1166 gap: 12.5px 1167 } 1168 1169 .ag-top-nav .ag-top-nav-item a { 1170 font-size: clamp(10px, 1vw, 12px); 1171 line-height: 100%; 1172 color: #ffffff; 1173 text-transform: uppercase; 1174 text-align: center; 1175 display: inline-block; 1176 vertical-align: center; 1177 } 1178 1179 .ag-top-nav .ag-top-nav-item span.mb-bhi-display span { 1180 font-size: clamp(10px, 1vw, 12px); 1181 line-height: 100%; 1182 color: #ffffff; 1183 text-transform: uppercase; 1184 text-align: center; 1185 display: inline-block; 1186 } 1187 1188 .ag-top-nav .ag-top-nav-item span.mb-bhi-display span b { 1189 color: #00a900; 1190 font-weight: bold; 1191 margin-right: 2px; 1192 } 1193 1194 .ag-top-nav .ag-top-nav-item span.mb-bhi-display { 1195 display: inline-block; 1196 vertical-align: top; 1197 } 1198 1199 1200 .ag-top-nav-mobile { 1201 padding: 12.5px; 1202 background: #000000; 1203 display: none; 1204 flex-flow: row nowrap; 1205 align-items: center; 1206 justify-content: center; 1207 position: sticky; 1208 top: 0; 1209 z-index: 150; 1210 gap: 12.5px 1211 } 1212 1213 .ag-top-nav-mobile .ag-top-nav-item a { 1214 font-size: clamp(9px, 1vw, 12px); 1215 line-height: 100%; 1216 color: #ffffff; 1217 text-transform: uppercase; 1218 text-align: center; 1219 display: inline-block; 1220 vertical-align: center; 1221 } 1222 1223 .ag-top-nav-mobile .ag-top-nav-item span.mb-bhi-display span { 1224 font-size: clamp(9px, 1vw, 12px); 1225 line-height: 100%; 1226 color: #ffffff; 1227 text-transform: uppercase; 1228 text-align: center; 1229 display: inline-block; 1230 } 1231 1232 .ag-top-nav-mobile .ag-top-nav-item span.mb-bhi-display span b { 1233 color: #00a900; 1234 font-weight: bold; 1235 margin-right: 2px; 1236 } 1237 1238 .ag-top-nav-mobile .ag-top-nav-item span.mb-bhi-display { 1239 display: inline-block; 1240 vertical-align: top; 1241 } 1242 1243 @media screen and (max-width: 769px) { 1244 .ag-top-nav { 1245 display: none 1246 } 1247 .ag-top-nav-mobile { 1248 display: flex; 1249 display: -webkit-flex; 1250 display: -ms-flexbox; 1251 } 1252 } 1253 1254 @media print { 1255 .ag-top-nav { 1256 display: none 1257 } 1258 .ag-top-nav-mobile { 1259 display: none; 1260 } 1261 } 1262 1263 </style> 1264 1265<header> 1266 <div class="ag-brand-logo"> 1267 <a data-ag-event="media_interaction" href="/" title="Toyota"> 1268 <img src="https://bucket.dealeralchemist.com/hubert-vester-toyota/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1" alt="Toyota" /> 1269 </a> 1270 </div> 1271 <div class="ag-dealer-logo"> 1272 <a data-ag-event="media_interaction" href="/" title=""> 1273 <h2></h2> 1274 1275 1276 </a> 1277 </div> 1278 <div class="ag-dealer-nav"> 1279 <nav class="ag-desktop-menu" aria-label="Desktop Menu"> 1280 <div id="main_nav_menu" class="menu-main-nav-menu-container"><ul id="menu-main-nav-menu" class="menu"><li id="menu-item-76682" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/new-vehicles/" class="menu-image-title-after"><span class="menu-image-title">New</span></a> 1281<ul> 1282 <li id="menu-item-76683" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/new-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Shop All New</span></a></li> 1283 <li id="menu-item-76694" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/toyota-safety-sense/" class="menu-image-title-after"><span class="menu-image-title">Toyota Safety Sense</span></a></li> 1284 <li id="menu-item-76709" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/incentives/" class="menu-image-title-after"><span class="menu-image-title">Toyota Incentives</span></a></li> 1285 <li id="menu-item-76693" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/toyotacare/" class="menu-image-title-after"><span class="menu-image-title">ToyotaCare</span></a></li> 1286 <li id="menu-item-76684" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/new-vehicles/?flags.type=Special" class="menu-image-title-after"><span class="menu-image-title">New Vehicle Specials</span></a></li> 1287 <li id="menu-item-76688" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/vehicle-finder-service/" class="menu-image-title-after"><span class="menu-image-title">Vehicle Finder Service</span></a></li> 1288 <li id="menu-item-76695" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/electrified-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Electrified Vehicles</span></a></li> 1289 <li id="menu-item-76696" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/college-rebate-program/" class="menu-image-title-after"><span class="menu-image-title">College Rebate Program</span></a></li> 1290 <li id="menu-item-77266" class="menu-half menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="https://www.hubertvestertoyota.com/vester-value-advantage/" class="menu-image-title-after"><span class="menu-image-title">Extras You Get Here</span></a></li> 1291 <li id="menu-item-76717" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/military-rebate-program/" class="menu-image-title-after"><span class="menu-image-title">Military Rebate Program</span></a></li> 1292 <li id="menu-item-76686" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="/research/" class="menu-image-title-after"><span class="menu-image-title">
1292Toyota Model Showroom</span></a></li> 1293 <li id="menu-item-76718" class="dv-submenu-model-selector menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="new" href="#!" class="menu-image-title-after"><span class="menu-image-title"> 1294 <style type='text/css'> 1295 header #menu-main-nav-menu li.has-sub ul .dv-submenu-item a:hover{ background-color: #000 !important }header #menu-main-nav-menu li.has-sub ul .dv-submenu-item a:hover span{ color: #fff !important }header #menu-main-nav-menu li.has-sub ul .dv-submenu-item a span{ color: #fff !important }#menu-main-nav-menu .dv-submenu-model-selector .dv-vehicle-menu-scroll { color: #fff !important }header #menu-main-nav-menu li.has-sub ul .dv-submenu-model-selector{ background-color: var(--primary-color) !important } 1296 </style> 1297 <style>#menu-main-nav-menu .dv-submenu-model-selector .dv-vehicle-menu-model-wrapper { overflow-y: auto !important; max-height: 300px !important; width: 100%;}</style> 1298
1298<script> 1299 $('.dv-submenu-model-selector > a').contents().unwrap(); 1300 $('.dv-submenu-model-selector > span').contents().unwrap(); 1301 </script>
1301 1302 <div class="dv-vehicle-menu-model-wrapper "> 1303 <div class="dv-submenu-dealer-models toyota-cars & minivans"> 1304 <p><a data-ag-event="cta_interaction" href="/new-vehicles/?make=Toyota&body=Sedan&body=Van" title="Shop Cars & Minivans" class='dv-submenu-bodystyle-link'>Cars & Minivans</a></p> 1305 <div class="dv-submenu-item-wrapper"> 1306 <div class="dv-submenu-item"> 1307 <a href="/new-vehicles/?make=Toyota&model=Corolla&model=Corolla%20Hatchback&model=Corolla%20Hybrid" title="Corolla" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1308 <div class="dv-submenu-item-img"> 1309 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/corolla-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Corolla" style="width: 50px !important"/> 1310 </div> 1311 <div class="dv-submenu-item-modelinfo"> 1312 <span class="dv-submenu-item-modelname">Corolla (11)</span> 1313 </div> 1314 </a> 1315 </div> <div class="dv-submenu-item"> 1316 <a href="/new-vehicles/?make=Toyota&model=GR Corolla" title="GR Corolla" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1317 <div class="dv-submenu-item-img"> 1318 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/gr-corolla-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="GR Corolla" style="width: 50px !important"/> 1319 </div> 1320 <div class="dv-submenu-item-modelinfo"> 1321 <span class="dv-submenu-item-modelname">GR Corolla (1)</span> 1322 </div> 1323 </a> 1324 </div> <div class="dv-submenu-item"> 1325 <a href="/research/supra/" title="GR Supra" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1326 <div class="dv-submenu-item-img"> 1327 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/supra-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="GR Supra" style="width: 50px !important"/> 1328 </div> 1329 <div class="dv-submenu-item-modelinfo"> 1330 <span class="dv-submenu-item-modelname">GR Supra (0)</span> 1331 </div> 1332 </a> 1333 </div> <div class="dv-submenu-item"> 1334 <a href="/research/gr86/" title="GR86" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1335 <div class="dv-submenu-item-img"> 1336 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/gr86-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="GR86" style="width: 50px !important"/> 1337 </div> 1338 <div class="dv-submenu-item-modelinfo"> 1339 <span class="dv-submenu-item-modelname">GR86 (0)</span> 1340 </div> 1341 </a> 1342 </div> <div class="dv-submenu-item"> 1343 <a href="/new-vehicles/?make=Toyota&model=Sienna" title="Sienna" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1344 <div class="dv-submenu-item-img"> 1345 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/sienna-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Sienna" style="width: 50px !important"/> 1346 </div> 1347 <div class="dv-submenu-item-modelinfo"> 1348 <span class="dv-submenu-item-modelname">Sienna (4)</span> 1349 </div> 1350 </a> 1351 </div> 1352 </div> 1353</div><div class="dv-submenu-dealer-models toyota-crossovers / trucks / suvs"> 1354 <p><a data-ag-event="cta_interaction" href="/new-vehicles/?make=Toyota&body=SUV&body=Truck&body=Crossover" title="Shop Crossovers / Trucks / SUVs" class='dv-submenu-bodystyle-link'>Crossovers / Trucks / SUVs</a></p> 1355 <div class="dv-submenu-item-wrapper"> 1356 <div class="dv-submenu-item"> 1357 <a href="/new-vehicles/?make=Toyota&model=4Runner&model=4Runner%20i-FORCE%20MAX" title="4Runner" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1358 <div class="dv-submenu-item-img"> 1359 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/4runner-w.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="4Runner" style="width: 50px !important"/> 1360 </div> 1361 <div class="dv-submenu-item-modelinfo"> 1362 <span class="dv-submenu-item-modelname">4Runner (3)</span> 1363 </div> 1364 </a> 1365 </div> <div class="dv-submenu-item"> 1366 <a href="/new-vehicles/?make=Toyota&model=Corolla%20Cross&model=Corolla%20Cross%20Hybrid" title="Corolla Cross" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1367 <div class="dv-submenu-item-img"> 1368 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/corolla-cross-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Corolla Cross" style="width: 50px !important"/> 1369 </div> 1370 <div class="dv-submenu-item-modelinfo"> 1371 <span class="dv-submenu-item-modelname">Corolla Cross (7)</span> 1372 </div> 1373 </a> 1374 </div> <div class="dv-submenu-item"> 1375 <a href="/new-vehicles/?make=Toyota&model=Grand%20Highlander&model=Grand%20Highlander%20Hybrid" title="Grand Highlander" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1376 <div class="dv-submenu-item-img"> 1377 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/grand-highlander-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Grand Highlander" style="width: 50px !important"/> 1378 </div> 1379 <div class="dv-submenu-item-modelinfo"> 1380 <span class="dv-submenu-item-modelname">Grand Highlander (6)</span> 1381 </div> 1382 </a> 1383 </div> <div class="dv-submenu-item"> 1384 <a href="/new-vehicles/?make=Toyota&model=Highlander&model=Highlander%20Hybrid" title="Highlander" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1385 <div class="dv-submenu-item-img"> 1386 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/highlander-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Highlander" style="width: 50px !important"/> 1387 </div> 1388 <div class="dv-submenu-item-modelinfo"> 1389 <span class="dv-submenu-item-modelname">Highlander (2)</span> 1390 </div> 1391 </a> 1392 </div> <div class="dv-submenu-item"> 1393 <a href="/new-vehicles/?make=Toyota&model=Land Cruiser" title="Land Cruiser" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1394 <div class="dv-submenu-item-img"> 1395 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/land-cruiser-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Land Cruiser" style="width: 50px !important"/> 1396 </div> 1397 <div class="dv-submenu-item-modelinfo"> 1398 <span class="dv-submenu-item-modelname">Land Cruiser (1)</span> 1399 </div> 1400 </a> 1401 </div> <div class="dv-submenu-item"> 1402 <a href="/new-vehicles/?make=Toyota&model=RAV4&model=RAV4%20Hybrid" title="RAV4" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1403 <div class="dv-submenu-item-img"> 1404 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/rav4-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="RAV4" style="width: 50px !important"/> 1405 </div> 1406 <div class="dv-submenu-item-modelinfo"> 1407 <span class="dv-submenu-item-modelname">RAV4 (15)</span> 1408 </div> 1409 </a> 1410 </div> <div class="dv-submenu-item"> 1411 <a href="/new-vehicles/?make=Toyota&model=Sequoia" title="Sequoia" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1412 <div class="dv-submenu-item-img"> 1413 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/sequoia-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Sequoia" style="width: 50px !important"/> 1414 </div> 1415 <div class="dv-submenu-item-modelinfo"> 1416 <span class="dv-submenu-item-modelname">Sequoia (3)</span> 1417 </div> 1418 </a> 1419 </div> <div class="dv-submenu-item"> 1420 <a href="/new-vehicles/?make=Toyota&model=Tacoma&model=Tacoma%20i-FORCE%20MAX" title="Tacoma" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1421 <div class="dv-submenu-item-img"> 1422 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/tacoma-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Tacoma" style="width: 50px !important"/> 1423 </div> 1424 <div class="dv-submenu-item-modelinfo"> 1425 <span class="dv-submenu-item-modelname">Tacoma (38)</span> 1426 </div> 1427 </a> 1428 </div> <div class="dv-submenu-item"> 1429 <a href="/new-vehicles/?make=Toyota&model=Tundra&model=Tundra%20i-FORCE%20MAX" title="Tundra" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1430 <div class="dv-submenu-item-img"> 1431 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/tundra-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Tundra" style="width: 50px !important"/> 1432 </div> 1433 <div class="dv-submenu-item-modelinfo"> 1434 <span class="dv-submenu-item-modelname">Tundra (8)</span> 1435 </div> 1436 </a> 1437 </div> 1438 </div> 1439</div><div class="dv-submenu-dealer-models toyota-electrified / hybrid"> 1440 <p><a data-ag-event="cta_interaction" href="/new-vehicles/?make=Toyota&fuel=Hybrid&fuel=Electric&fuel=Battery%20Electric&fuel=Plug-in%20Hybrid" title="Shop Electrified / Hybrid" class='dv-submenu-bodystyle-link'>Electrified / Hybrid</a></p> 1441 <div class="dv-submenu-item-wrapper"> 1442 <div class="dv-submenu-item"> 1443 <a href="/new-vehicles/?make=Toyota&model=bZ" title="bZ" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1444 <div class="dv-submenu-item-img"> 1445 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/bz4x-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="bZ" style="width: 50px !important"/> 1446 </div> 1447 <div class="dv-submenu-item-modelinfo"> 1448 <span class="dv-submenu-item-modelname">bZ (1)</span> 1449 </div> 1450 </a> 1451 </div> <div class="dv-submenu-item"> 1452 <a href="/research/bz-woodland/" title="bZ Woodland" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1453 <div class="dv-submenu-item-img"> 1454 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/bzwoodland-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="bZ Woodland" style="width: 50px !important"/> 1455 </div> 1456 <div class="dv-submenu-item-modelinfo"> 1457 <span class="dv-submenu-item-modelname">bZ Woodland (0)</span> 1458 </div> 1459 </a> 1460 </div> <div class="dv-submenu-item"> 1461 <a href="/research/c-hr/" title="C-HR" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1462 <div class="dv-submenu-item-img"> 1463 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/c-hr-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="C-HR" style="width: 50px !important"/> 1464 </div> 1465 <div class="dv-submenu-item-modelinfo"> 1466 <span class="dv-submenu-item-modelname">C-HR (0)</span> 1467 </div> 1468 </a> 1469 </div> <div class="dv-submenu-item"> 1470 <a href="/new-vehicles/?make=Toyota&model=Camry" title="Camry" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1471 <div class="dv-submenu-item-img"> 1472 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/camry-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Camry" style="width: 50px !important"/> 1473 </div> 1474 <div class="dv-submenu-item-modelinfo"> 1475 <span class="dv-submenu-item-modelname">Camry (22)</span> 1476 </div> 1477 </a> 1478 </div> <div class="dv-submenu-item"> 1479 <a href="/research/crown/" title="Crown" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1480 <div class="dv-submenu-item-img"> 1481 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/crown-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Crown" style="width: 50px !important"/> 1482 </div> 1483 <div class="dv-submenu-item-modelinfo"> 1484 <span class="dv-submenu-item-modelname">Crown (0)</span> 1485 </div> 1486 </a> 1487 </div> <div class="dv-submenu-item"> 1488 <a href="/new-vehicles/?make=Toyota&model=Crown Signia" title="Crown Signia" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1489 <div class="dv-submenu-item-img"> 1490 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/crown-signia-c.png?auto=compress%2Cformat&ixlib=php-3.3.1&width=50" alt="Crown Signia" style="width: 50px !important"/> 1491 </div> 1492 <div class="dv-submenu-item-modelinfo"> 1493 <span class="dv-submenu-item-modelname">Crown Signia (1)</span> 1494 </div> 1495 </a> 1496 </div> <div class="dv-submenu-item"> 1497 <a href="/new-vehicles/?make=Toyota&model=Prius" title="Prius" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1498 <div class="dv-submenu-item-img"> 1499 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/prius-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Prius" style="width: 50px !important"/> 1500 </div> 1501 <div class="dv-submenu-item-modelinfo"> 1502 <span class="dv-submenu-item-modelname">Prius (1)</span> 1503 </div> 1504 </a> 1505 </div> <div class="dv-submenu-item"> 1506 <a href="/research/prius-plug-in-hybrid/" title="Prius Plug-in Hybrid" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1507 <div class="dv-submenu-item-img"> 1508 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/prius-prime-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="Prius Plug-in Hybrid" style="width: 50px !important"/> 1509 </div> 1510 <div class="dv-submenu-item-modelinfo"> 1511 <span class="dv-submenu-item-modelname">Prius Plug-in Hybrid (0)</span> 1512 </div> 1513 </a> 1514 </div> <div class="dv-submenu-item"> 1515 <a href="/new-vehicles/?make=Toyota&model=RAV4%20Plug-in%20Hybrid" title="RAV4 Plug-in Hybrid" data-ag-event="cta_interaction" class='dv-submenu-item-link'> 1516 <div class="dv-submenu-item-img"> 1517 <img src="https://bucket.dealeralchemist.com/assets/oem/toyota/carousel/jellies/rav4-prime-c.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=50" alt="RAV4 Plug-in Hybrid" style="width: 50px !important"/> 1518 </div> 1519 <div class="dv-submenu-item-modelinfo"> 1520 <span class="dv-submenu-item-modelname">RAV4 Plug-in Hybrid (2)</span> 1521 </div> 1522 </a> 1523 </div> 1524 </div> 1525</div> 1526 </div> 1527
1527<script> 1528 $('.dv-submenu-model-selector a:empty').remove(); 1529 $('.dv-vehicle-menu-model-wrapper > a:first-of-type').remove(); 1530 $('.dv-submenu-model-selector .dv-submenu-dealer-models > a:first-child').contents().unwrap(); 1531 </script>
1531 1532 <div class="dv-vehicle-menu-scroll">Scroll For More</div></span></a></li> 1533</ul> 1534</li> 1535<li id="menu-item-76703" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/used-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Used</span></a> 1536<ul> 1537 <li id="menu-item-76719" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="https://www.hubertvestertoyota.com/used-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Shop All Used</span></a></li> 1538 <li id="menu-item-76708" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="/used-vehicles/?flags.type=Special" class="menu-image-title-after"><span class="menu-image-title">Used Vehicle Specials</span></a></li> 1539 <li id="menu-item-77267" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="https://www.hubertvestertoyota.com/vester-value-advantage/" class="menu-image-title-after"><span class="menu-image-title">Extra You Get at Vester</span></a></li> 1540 <li id="menu-item-76702" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="/used-vehicles/?finalPriceRange=$10,000%20and%20Below" class="menu-image-title-after"><span class="menu-image-title">Priced Under $10K</span></a></li> 1541 <li id="menu-item-77268" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="/used-vehicles/?finalPriceRange=$10,000%20and%20Below&finalPriceRange=$10,000%20-%20$20,000" class="menu-image-title-after"><span class="menu-image-title">Priced Under $20K</span></a></li> 1542 <li id="menu-item-77269" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="used" href="/used-vehicles/?finalPriceRange=$10,000%20and%20Below&finalPriceRange=$10,000%20-%20$20,000&finalPriceRange=$20,000%20-%20$30,000" class="menu-image-title-after"><span class="menu-image-title">Priced Under $30k</span></a></li> 1543</ul> 1544</li> 1545<li id="menu-item-76712" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/service/" class="menu-image-title-after"><span class="menu-image-title">Service & Parts</span></a> 1546<ul> 1547 <li id="menu-item-76724" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/" class="menu-image-title-after"><span class="menu-image-title">Service Center</span></a></li> 1548 <li id="menu-item-76722" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/parts/" class="menu-image-title-after"><span class="menu-image-title">Parts Center</span></a></li> 1549 <li id="menu-item-76725" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/schedule-service/" class="menu-image-title-after"><span class="menu-image-title">Schedule Service</span></a></li> 1550 <li id="menu-item-76740" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" target="_blank" href="https://autoparts.hubertvestertoyota.com/" class="menu-image-title-after"><span class="menu-image-title">Order Parts</span></a></li> 1551 <li id="menu-item-76783" class="menu-half menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="https://www.hubertvestertoyota.com/specials/service/" class="menu-image-title-after"><span class="menu-image-title">Service & Parts Specials</span></a></li> 1552 <li id="menu-item-76726" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/oil-change/" class="menu-image-title-after"><span class="menu-image-title">Oil Change</span></a></li> 1553 <li id="menu-item-76727" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/tires/" class="menu-image-title-after"><span class="menu-image-title">Tires</span></a></li> 1554 <li id="menu-item-76754" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/brakes/" class="menu-image-title-after"><span class="menu-image-title">Brakes</span></a></li> 1555 <li id="menu-item-76755" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/batteries/" class="menu-image-title-after"><span class="menu-image-title">Batteries</span></a></li> 1556 <li id="menu-item-76756" class="menu-half menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" target="_blank" href="https://www.toyota.com/recall/" class="menu-image-title-after"><span class="menu-image-title">Check For Recalls</span></a></li> 1557</ul> 1558</li> 1559<li id="menu-item-77270" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/rent-a-car/" class="menu-image-title-after"><span class="menu-image-title">Rent A Toyota</span></a> 1560<ul> 1561 <li id="menu-item-77271" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="" href="https://www.hubertvestertoyota.com/rent-a-car/" class="menu-image-title-after"><span class="menu-image-title">Rent A Toyota</span></a></li> 1562 <li id="menu-item-77272" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="" target="_blank" href="https://www.toyota.com/rental/request/#!/model-date?dealerCode=32136" class="menu-image-title-after"><span class="menu-image-title">Reserve a Toyota</span></a></li> 1563</ul> 1564</li> 1565<li id="menu-item-76707" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/finance/" class="menu-image-title-after"><span class="menu-image-title">Finance</span></a> 1566<ul> 1567 <li id="menu-item-76713" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/finance/" class="menu-image-title-after"><span class="menu-image-title">Finance Center</span></a></li> 1568 <li id="menu-item-76714" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/finance/finance-application/" class="menu-image-title-after"><span class="menu-image-title">Get Pre-Qualified</span></a></li> 1569 <li id="menu-item-76720" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="https://www.hubertvestertoyota.com/finance/payments-calculator/" class="menu-image-title-after"><span class="menu-image-title">Payment Calculator</span></a></li> 1570 <li id="menu-item-76710" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/value-trade/" class="menu-image-title-after"><span class="menu-image-title">Value Your Trade</span></a></li> 1571 <li id="menu-item-76715" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/lease-trade-in/" class="menu-image-title-after"><span class="menu-image-title">Lease Trade In</span></a></li> 1572 <li id="menu-item-76723" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/finance/buy-vs-lease/" class="menu-image-title-after"><span class="menu-image-title">Buy vs Lease</span></a></li> 1573</ul> 1574</li> 1575<li id="menu-item-77274" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/hubert-vester-pledge/" class="menu-image-title-after"><span class="menu-image-title">Why Choose Vester</span></a> 1576<ul> 1577 <li id="menu-item-77275" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/vester-value-advantage/" class="menu-image-title-after"><span class="menu-image-title">Extras You Get a Vester</span></a></li> 1578 <li id="menu-item-77276" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/hubert-vester-pledge/" class="menu-image-title-after"><span class="menu-image-title">Our Promise to You</span></a></li> 1579 <li id="menu-item-77273" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/shop-at-home/" class="menu-image-title-after"><span class="menu-image-title">Shop at Home</span></a></li> 1580</ul> 1581</li> 1582<li id="menu-item-76745" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/contact/" class="menu-image-title-after"><span class="menu-image-title">About</span></a> 1583<ul> 1584 <li id="menu-item-76750" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/about/" class="menu-image-title-after"><span class="menu-image-title">About Us</span></a></li> 1585 <li id="menu-item-76749" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/contact/" class="menu-image-title-after"><span class="menu-image-title">Contact Us</span></a></li> 1586 <li id="menu-item-77279" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/hours-and-directions/" class="menu-image-title-after"><span class="menu-image-title">Hours & Directions</span></a></li> 1587 <li id="menu-item-76752" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/careers/" class="menu-image-title-after"><span class="menu-image-title">Careers</span></a></li> 1588 <li id="menu-item-77278" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/set-tact-program/" class="menu-image-title-after"><span class="menu-image-title">SET TACT Program</span></a></li> 1589 <li id="menu-item-76757" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/reviews/" class="menu-image-title-after"><span class="menu-image-title">Reviews</span></a></li> 1590 <li id="menu-item-76753" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/privacy-policy/" class="menu-image-title-after"><span class="menu-image-title">Privacy Policy</span></a></li> 1591</ul> 1592</li> 1593</ul></div> </nav> 1594 </div> 1595 <div class="ag-dealer-reviews"> 1596 <a data-ag-event="cta_interaction" href="/reviews/" title="Google Reviews"> 1597
1597<script type="application/ld+json"> 1598{ 1599 "@context": "https://schema.org/", 1600 "@type": "AggregateRating", 1601 "itemReviewed": { 1602 "@type": "AutomotiveBusiness", 1603 "image": "https://bucket.dealervenom.com/assets/oem/toyota/favicon/toyota-red-favicon.ico?auto=compres&format&ixlib=php-1.2.1&width=16", 1604 "name": "", 1605 "telephone": "252.293.6513", 1606 "address" : { 1607 "@type": "PostalAddress", 1608 "streetAddress": "3712 Raleigh Rd Pkwy W", 1609 "addressLocality": "NC", 1610 "postalCode": "27896", 1611 "addressCountry": "US" 1612 } 1613 }, 1614 "ratingValue": "4.6", 1615 "bestRating": "5", 1616 "ratingCount": "1457" 1617} 1618</script>
1618 1619 1620<div class="dv-reviews-badge " style="display: none;"> 1621 <div class="dv-reviews-badge-col"> 1622 <img src="https://bucket.dealeralchemist.com/assets/reviews/google_small_icon.png?auto=compress%2Cformat&ixlib=php-1.2.1" alt="Google Logo"> 1623 <p class="dv-reviews-badge-score">4.6</p> 1624 </div> 1625 <div class="dv-reviews-badge-col dv-reviews-badge-col-stack"> 1626 <p class="dv-review-badge-rating"><i class= 'fas fa-star'></i><i class= 'fas fa-star'></i><i class= 'fas fa-star'></i><i class= 'fas fa-star'></i><i class='fas fa-star-half-alt'></i></p> 1627 <p class="dv-review-badge-count">1457 Reviews</p> 1628 </div> 1629</div> </a> 1630 </div> 1631 <div class="ag-dealer-info"> 1632 <a data-ag-event="clickToCall|Sales" href="tel:252.293.6513" title="Call "> 1633 252.293.6513 </a> 1634 <a data-ag-event="getDirections" href="/hours-and-directions/" title="Get hours & directions to "> 1635 <span data-fetch-shortcode data-code="mbhi" data-arguments="location="Sales" includetime="" includeday="" format="12" approximation="1" openingsoonmessagetime="2700" closingsoonmessagetime="2700" openmessage="&lt;span class=&quot;mbhi_dv_header mbhi_open&quot;&gt;&lt;b&gt;Open&lt;/b&gt;&lt;/span&gt; {from} - {to}" closedmessage="&lt;span class=&quot;mbhi_dv_header mbhi_closed&quot;&gt;Now Closed&lt;/span&gt;" openingsoonmessage="Opening in {x} minutes" closingsoonmessage="Closing in {x} minutes" removezeroes="1" extra_classes="" show_specialdate_messages="1" show_vacation_messages="" vacation_message_closed="" specialdate_message_open="" specialdate_message_closed="" from="" to="" loading="Welcome!" display="consolidated"">Welcome!</span> </a> 1636 </div> 1637 <div class="nav-below-btn-toggle"> 1638 <div id="nav-icon-wrapper"> 1639 <span style="background-color: #000000"></span> 1640 <span style="background-color: #000000"></span> 1641 <span style="background-color: #000000"></span> 1642 <span style="background-color: #000000"></span> 1643 </div> 1644 </div></header> 1645 1646<style> 1647 .dv-header-lower { 1648 display: none; 1649 background: var(--primary-color); 1650 } 1651 1652 .dv-header-lower:hover { 1653 cursor: pointer; 1654 } 1655 1656 @media screen and (max-width: 768px) { 1657 .dv-header-lower.dv-header-lower-closed { 1658 display: none !important 1659 } 1660 1661 .dv-header-lower { 1662 display: flex; 1663 display: -webkit-flex; 1664 display: -ms-flexbox; 1665 align-items: center; 1666 justify-content: center; 1667 text-align: center; 1668 width: 100%; 1669 height: auto; 1670 position: sticky; 1671 z-index: 100; 1672 left: 0; 1673 right: 0; 1674 top: 75px !important 1675 } 1676 } 1677 1678 .dv-header-lower .dv-header-col { 1679 flex: 1 1 33.333%; 1680 width: 33.333%; 1681 } 1682 1683 .dv-header-lower .dv-header-col.hide { 1684 display: none 1685 } 1686 1687 .dv-header-lower .dv-header-col:not(:first-child) { 1688 position: relative; 1689 } 1690 1691 .dv-header-lower .dv-header-col:not(:first-child):before { 1692 position: absolute; 1693 content: ''; 1694 left: 0; 1695 height: 50%; 1696 top: 25%; 1697 z-index: 0; 1698 width: 1px; 1699 background-color: #fff; 1700 } 1701 1702 .dv-header-lower .dv-header-col a { 1703 padding: 15px 5px; 1704 font-size: 12px; 1705 display: block; 1706 color: #ffffff; 1707 text-decoration: none; 1708 font-family: inherit; 1709 text-decoration: none; 1710 } 1711 1712 .dv-header-lower .dv-header-col a i { 1713 margin-right: 5px; 1714 } 1715 1716 /* 1717 * Search Overlay 1718 */ 1719 1720 .ag-header-search-overlay { 1721 height: 0; 1722 width: 100%; 1723 background: var(--primary-color); 1724 opacity: 0; 1725 visibility: hidden; 1726 transition: opacity 200ms ease-out; 1727 -webkit-transition: opacity 200ms ease-out; 1728 -moz-transition: opacity 200ms ease-out; 1729 box-sizing: border-box; 1730 } 1731 1732 .ag-header-search-overlay * { 1733 box-sizing: border-box; 1734 } 1735 1736 .ag-header-search-overlay .ag-header-search-overlay-wrapper { 1737 display: flex; 1738 display: -webkit-flex; 1739 display: -ms-flexbox; 1740 } 1741 1742 .ag-header-search-overlay.active { 1743 position: fixed; 1744 height: auto; 1745 padding: 25px; 1746 top: 75px; 1747 width: 100%; 1748 z-index: 150; 1749 visibility: visible; 1750 background: #fff; 1751 display: flex; 1752 display: -webkit-flex; 1753 display: -ms-flexbox; 1754 flex-flow: column nowrap; 1755 align-items: center; 1756 justify-content: center; 1757 opacity: 1; 1758 box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1); 1759 transition: opacity 200ms ease-in; 1760 -webkit-transition: opacity 200ms ease-in; 1761 -moz-transition: opacity 200ms ease-in; 1762 } 1763 1764 .ag-header-search-overlay .ag-header-search-overlay-container { 1765 padding: 0; 1766 margin: 0; 1767 position: relative; 1768 width: 80% 1769 } 1770 1771 .ag-header-search-overlay .ag-header-search-overlay-container .ag-header-search-overlay-close { 1772 padding: 0 12.5px; 1773 width: fit-content; 1774 background-color: var(--primary-color); 1775 display: flex; 1776 display: -webkit-flex; 1777 display: -ms-flexbox; 1778 flex-flow: column nowrap; 1779 align-items: center; 1780 justify-content: center; 1781 } 1782 1783 .ag-header-search-overlay .ag-header-search-overlay-container .ag-header-search-overlay-close:hover { 1784 cursor: pointer; 1785 background-color: var(--secondary-color) 1786 } 1787 1788 .ag-header-search-overlay .ag-header-search-overlay-container .ag-header-search-overlay-close span { 1789 color: #fff; 1790 font-size: 10px; 1791 text-transform: uppercase; 1792 } 1793 1794 .ag-header-search-overlay .ag-header-search-cta-group { 1795 display: flex; 1796 display: -webkit-flex; 1797 display: -ms-flexbox; 1798 flex-flow: row nowrap; 1799 justify-content: center; 1800 align-items: center; 1801 gap: 25px; 1802 padding-top: 25px; 1803 } 1804 1805 .ag-header-search-overlay .ag-header-search-cta-group a { 1806 display: block; 1807 background-color: var(--primary-color); 1808 color: #fff; 1809 border: 0; 1810 padding: 12.5px 25px; 1811 font-size: 12px; 1812 } 1813 1814 .ag-header-search-overlay .ag-header-search-cta-group a:hover { 1815 background-color: var(--secondary-color) 1816 } 1817 1818 @media screen and (max-width: 768px) { 1819 .ag-header-search-overlay.active { 1820 top: 75px; 1821 } 1822 1823 .ag-header-search-overlay .ag-header-search-overlay-container { 1824 width: 100% 1825 } 1826 } 1827 1828 @media screen and (max-width: 480px) { 1829 .ag-header-search-overlay .ag-header-search-cta-group a { 1830 padding: 12.5px 1831 } 1832 } 1833</style> 1834 1835<div class="dv-header-lower" style="top: 75px"> 1836 <div class="dv-header-col"> 1837 <a href="tel:252.293.6513" 1838 target="_self" 1839 title="Sales" 1840 data-ag-event="clickToCall|Sales"> 1841 <i class="fa fa-phone"></i> 1842 Sales </a> 1843 </div> 1844 <div class="dv-header-col"> 1845 <a href="tel:252.293.6513" 1846 target="_self" 1847 title="Service" 1848 data-ag-event="clickToCall|Service"> 1849 <i class="fa fa-phone"></i> 1850 Service </a> 1851 </div> 1852 <div class="dv-header-col"> 1853 <a href="https://maps.app.goo.gl/3y3jqzq82XTNvT8q7" 1854 target="_blank" 1855 title="Get Directions" 1856 data-ag-event="getDirections"> 1857 <i class="fa fas fa-map-marker-alt"></i> 1858 Get Directions </a> 1859 </div> 1860 </div> 1861 1862<link rel="preload" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/header/header-pulldown.css?v=1.761.775" as="style"> 1863<link rel="stylesheet" href="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/header/header-pulldown.css?v=1.761.775" type="text/css"> 1864<style> 1865.dv-fw-search .dv-fw-mobile-menu-wrapper>ul.dv-fw-mobile-menu-selector, 1866.dv-fw-search .dv-fw-mobile-menu-wrapper>ul .dv-fw-mobile-menu-item { 1867 background-color: #eb0a1e; 1868} 1869 1870.dv-fw-search .dv-fw-mobile-menu-wrapper>ul .dv-fw-mobile-menu-item.active { 1871 background-color: #000000; 1872} 1873 1874.dv-fw-search .dv-fw-mobile-menu-wrapper>ul .dv-fw-mobile-menu-item>a { 1875 border-color: #ffffff; 1876 color: #fff; 1877} 1878 1879.dv-fw-search .dv-fw-mobile-menu-wrapper .dv-mobile-menu-btn { 1880 color: #fff !important; 1881 background: #eb0a1e !important; 1882} 1883 1884.dv-fw-search .dv-fw-mobile-menu-wrapper .dv-mobile-menu-btn:hover { 1885 color: #fff !important; 1886 background: #000000 !important; 1887} 1888 1889@media screen and (max-width: 1335px) { 1890 .dv-fw-search { 1891 background: transparent; 1892 min-width: 400px; 1893 width: 33.333%; 1894 } 1895 1896 /* .dv-fw-search.dv-toggle-open { 1897 border-top: 1px solid transparent; 1898 } */ 1899 body.mobile-menu-open { 1900 position: relative; 1901 } 1902 1903 body.mobile-menu-open:before { 1904 content: ''; 1905 position: absolute; 1906 top: 0; 1907 left: 0; 1908 width: 100%; 1909 height: 100%; 1910 background: rgba(0, 0, 0, 0.5); 1911 z-index: 3; 1912 } 1913 1914 .dv-fw-search .dv-fw-search-wrapper { 1915 display: none; 1916 } 1917 1918 .dv-fw-search .dv-fw-mobile-menu-wrapper { 1919 display: flex; 1920 background: #fff; 1921 } 1922 1923 .dv-desktop-menu, 1924 #desktop-nav { 1925 display: none !important; 1926 } 1927} 1928 1929@media screen and (max-width: 768px) { 1930 .dv-fw-search { 1931 min-width: 100%; 1932 width: 100%; 1933 } 1934} 1935</style> 1936<style> 1937/* min width redux */ 1938@media screen and (min-width: calc(1335px + 1px)) { 1939 1940 .dv-fw-search, 1941 .nav-below-btn-toggle { 1942 display: none !important; 1943 } 1944} 1945 1946@media screen and (max-width: 1335px) { 1947 .dv-desktop-menu #desktop-nav { 1948 display: none !important; 1949 } 1950} 1951</style> 1952 1953<div class="dv-fw-search"> 1954 <div class="dv-fw-search-wrapper"> 1955 </div> 1956 <div class="dv-fw-mobile-menu-wrapper"> 1957 <ul class="dv-fw-mobile-menu-selector"> 1958 <li class="dv-fw-mobile-menu-item active">
1959 <a href="#" title="Mobile Menu"> 1960 <span><i class="fal fa-bars"></i></span> 1961 <span>Menu</span> 1962 </a> 1963 </li> 1964 <li class="dv-fw-mobile-menu-item"> 1965 <a href="#" title="Mobile Menu"> 1966 <span><i class="fal fa-phone"></i></span> 1967 <span>Call</span> 1968 </a> 1969 </li> 1970 <li class="dv-fw-mobile-menu-item"> 1971 <a href="#" title="Mobile Menu"> 1972 <span><i class="fal fa-map-marker-alt"></i></span> 1973 <span>Location</span> 1974 </a> 1975 </li> 1976 <li class="dv-fw-mobile-menu-item"> 1977 <a href="#" title="Mobile Menu"> 1978 <span><i class="fal fa-clock"></i></span> 1979 <span>Hours</span> 1980 </a> 1981 </li> 1982 </ul> 1983 <ul class="dv-fw-mobile-menu-content"> 1984 <li class="dv-fw-mobile-menu-item-content active"> 1985 <div class="dv-mobile-menu-inner"> 1986 <nav class="dv-mobile-menu" aria-label="Mobile Menu"> 1987 <div id="mobile_main_nav_menu" class="menu-mobile-menu-container"><ul id="menu-mobile-menu" class="menu"><li id="menu-item-76662" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/new-vehicles/" class="menu-image-title-after"><span class="menu-image-title">New Vehicles</span></a></li> 1988<li id="menu-item-76677" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/used-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Used Vehicles</span></a></li> 1989<li id="menu-item-76679" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/used-vehicles/?flags.type=Certified" class="menu-image-title-after"><span class="menu-image-title">Certified Pre-Owned Inventory</span></a></li> 1990<li id="menu-item-76666" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/value-trade/" class="menu-image-title-after"><span class="menu-image-title">Value Your Trade</span></a></li> 1991<li id="menu-item-76665" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/vehicle-finder-service/" class="menu-image-title-after"><span class="menu-image-title">Vehicle Finder Service</span></a></li> 1992<li id="menu-item-77281" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="https://www.hubertvestertoyota.com/vester-value-advantage/" class="menu-image-title-after"><span class="menu-image-title">Extras You Get Here</span></a></li> 1993<li id="menu-item-76671" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="#/" class="menu-image-title-after"><span class="menu-image-title">Service & Parts</span></a> 1994<ul> 1995 <li id="menu-item-76669" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/" class="menu-image-title-after"><span class="menu-image-title">Service Center</span></a></li> 1996 <li id="menu-item-76670" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/service/schedule-service/" class="menu-image-title-after"><span class="menu-image-title">Schedule Service</span></a></li> 1997 <li id="menu-item-76672" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" href="/parts/" class="menu-image-title-after"><span class="menu-image-title">Parts Center</span></a></li> 1998 <li id="menu-item-76673" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" target="_blank" href="https://autoparts.hubertvestertoyota.com/" class="menu-image-title-after"><span class="menu-image-title">Order Parts</span></a></li> 1999 <li id="menu-item-76780" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="service-&-parts" target="_blank" href="https://www.toyota.com/recall/" class="menu-image-title-after"><span class="menu-image-title">Check For Recalls</span></a></li> 2000</ul> 2001</li> 2002<li id="menu-item-77282" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-has-children active has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/#" class="menu-image-title-after"><span class="menu-image-title">Rent A Toyota</span></a> 2003<ul> 2004 <li id="menu-item-77283" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="rent-a-toyota" href="https://www.hubertvestertoyota.com/rent-a-car/" class="menu-image-title-after"><span class="menu-image-title">Rent A Toyota</span></a></li> 2005 <li id="menu-item-77284" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="rent-a-toyota" target="_blank" href="https://www.toyota.com/rental/request/#!/model-date?dealerCode=32136" class="menu-image-title-after"><span class="menu-image-title">Reserve a Toyota</span></a></li> 2006</ul> 2007</li> 2008<li id="menu-item-76663" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="#/" class="menu-image-title-after"><span class="menu-image-title">Finance</span></a> 2009<ul> 2010 <li id="menu-item-76668" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/finance/" class="menu-image-title-after"><span class="menu-image-title">Finance Center</span></a></li> 2011 <li id="menu-item-76667" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="finance" href="/finance/finance-application/" class="menu-image-title-after"><span class="menu-image-title">Finance Application</span></a></li> 2012</ul> 2013</li> 2014<li id="menu-item-76664" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="#/" class="menu-image-title-after"><span class="menu-image-title">Specials</span></a> 2015<ul> 2016 <li id="menu-item-76674" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="/incentives/" class="menu-image-title-after"><span class="menu-image-title">Toyota Incentives</span></a></li> 2017 <li id="menu-item-76675" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="/new-vehicles/?flags.type=Special" class="menu-image-title-after"><span class="menu-image-title">New Vehicle Specials</span></a></li> 2018 <li id="menu-item-76676" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="/used-vehicles/?flags.type=Special" class="menu-image-title-after"><span class="menu-image-title">Used Vehicle Specials</span></a></li> 2019 <li id="menu-item-76784" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="https://www.hubertvestertoyota.com/specials/service/" class="menu-image-title-after"><span class="menu-image-title">Service & Parts Specials</span></a></li> 2020 <li id="menu-item-76699" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="https://www.hubertvestertoyota.com/college-rebate-program/" class="menu-image-title-after"><span class="menu-image-title">College Rebate Program</span></a></li> 2021 <li id="menu-item-76700" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="specials" href="https://www.hubertvestertoyota.com/military-rebate-program/" class="menu-image-title-after"><span class="menu-image-title">Military Rebate Program</span></a></li> 2022</ul> 2023</li> 2024<li id="menu-item-77285" class="menu-item menu-item-type-custom menu-item-object-custom current-menu-item current_page_item menu-item-has-children active has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="/#" class="menu-image-title-after"><span class="menu-image-title">Why Choose Vester</span></a> 2025<ul> 2026 <li id="menu-item-77288" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/vester-value-advantage/" class="menu-image-title-after"><span class="menu-image-title">Extras You Get a Vester</span></a></li> 2027 <li id="menu-item-77287" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/hubert-vester-pledge/" class="menu-image-title-after"><span class="menu-image-title">Our Promise to You</span></a></li> 2028 <li id="menu-item-77286" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="why-choose-vester" href="https://www.hubertvestertoyota.com/shop-at-home/" class="menu-image-title-after"><span class="menu-image-title">Shop at Home</span></a></li> 2029</ul> 2030</li> 2031<li id="menu-item-76685" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-has-children has-sub"><a data-ag-event="menu_interaction" style="" data-element_type="home" href="#/" class="menu-image-title-after"><span class="menu-image-title">About</span></a> 2032<ul> 2033 <li id="menu-item-76690" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/about/" class="menu-image-title-after"><span class="menu-image-title">About Us</span></a></li> 2034 <li id="menu-item-76689" class="menu-item menu-item-type-custom menu-item-object-custom"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="/contact/" class="menu-image-title-after"><span class="menu-image-title">Contact Us</span></a></li> 2035 <li id="menu-item-77290" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/hours-and-directions/" class="menu-image-title-after"><span class="menu-image-title">Hours & Directions</span></a></li>
2036 <li id="menu-item-77289" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/careers/" class="menu-image-title-after"><span class="menu-image-title">Careers</span></a></li> 2037 <li id="menu-item-77292" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/set-tact-program/" class="menu-image-title-after"><span class="menu-image-title">SET TACT Program</span></a></li> 2038 <li id="menu-item-77293" class="menu-item menu-item-type-post_type menu-item-object-page"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/reviews/" class="menu-image-title-after"><span class="menu-image-title">Reviews</span></a></li> 2039 <li id="menu-item-77295" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-privacy-policy"><a data-ag-event="menu_interaction" style="" data-element_type="about" href="https://www.hubertvestertoyota.com/privacy-policy/" class="menu-image-title-after"><span class="menu-image-title">Privacy Policy</span></a></li> 2040</ul> 2041</li> 2042</ul></div> </nav> 2043 </div> 2044 </li> 2045 <li class="dv-fw-mobile-menu-item-content"> 2046 <div class="dv-mobile-menu-inner"> 2047 <div class="dv-mobile-menu-inner-header">Call</div> 2048 <div class="dv-mobile-menu-inner-body dv-dealer-call"> 2049 <ul> 2050 <li> 2051 <span>Sales</span> 2052 <a href="tel:252.293.6513" title="Call Sales 252.293.6513" data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales"><i class="fal fa-mobile"></i> 252.293.6513</a> 2053 </li> 2054 <li> 2055 <span>Service</span> 2056 <a href="tel:252.293.6513" title="Call Service 252.293.6513" data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Service"><i class="fal fa-mobile"></i> 252.293.6513</a> 2057 </li> 2058 <li> 2059 <span>Parts</span> 2060 <a href="tel:252.293.6513" title="Call Parts 252.293.6513" data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Parts"><i class="fal fa-mobile"></i> 252.293.6513</a> 2061 </li> 2062 <!--<li> 2063 <span>Collision Center</span> 2064 <a href="tel:COLLISION NUMBER" title="Call Collision Center COLLISION NUMBER" data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Collision"><i class="fal fa-mobile"></i> COLLISION NUMBER</a> 2065 </li>--> 2066</ul> </div> 2067 </div> 2068 </li> 2069 <li class="dv-fw-mobile-menu-item-content"> 2070 <div class="dv-mobile-menu-inner"> 2071 <div class="dv-mobile-menu-inner-header">Location</div> 2072 <div class="dv-mobile-menu-inner-body dv-dealer-location"> 2073 <ul> 2074 <li> 2075 <span><i class="fal fa-map-marker-alt"></i> </span> 2076 <a target='_blank' href="https://maps.app.goo.gl/3y3jqzq82XTNvT8q7" title="" data-aga-event="getDirections">3712 Raleigh Rd Pkwy W<br> Wilson NC 27896</a> 2077 <a target='_blank' href="https://maps.app.goo.gl/3y3jqzq82XTNvT8q7" title="" class="dv-mobile-menu-btn" data-aga-event="getDirections">Get Directions</a> 2078 </li> 2079 <!--<li> 2080 <span><i class="fal fa-map-marker-alt"></i> Collision Center</span> 2081 <a target='_blank' href="" title="" data-aga-event="getDirections"></a> 2082 <a target='_blank' href="" title="" class="dv-mobile-menu-btn" data-aga-event="getDirections">Get Directions</a> 2083 </li>--> 2084 2085</ul> </div> 2086 </div> 2087 </li> 2088 <li class="dv-fw-mobile-menu-item-content"> 2089 <div class="dv-mobile-menu-inner"> 2090 <div class="dv-mobile-menu-inner-header">Hours</div> 2091 <div class="dv-mobile-menu-inner-body dv-dealer-hours"> 2092 <ul> 2093 <li> 2094 <span style='font-weight:800;'>Sales <i class="fal fa-clock"></i></span> 2095 <span data-fetch-shortcode data-code="mbhi_hours" data-arguments="location="Sales" format="12" display="table" output="1" includeholidays="true" includevacations="" abbreviatedays="" consolidationseparator=" - " hourseparator=" - " entryseparator=", " mhbr="1" showonlytoday="" dayentryseparator=" " removezeroes="1" seo="" for_admin="" hide_hours="" startonsunday="" extra_classes="" dates_in_past="1" replace_with_specials="true" replace_with_vacations="" date_format="day first" replaced_vacations_format="{day} ({name})" replaced_specials_format="{day} *({month_short} {day_of_month})" included_vacations_format="{from_day_of_month} {from_month_short} - {to_day_of_month} {to_month_short}" included_specials_format="{day_of_month} {month_short}" day_format="{day}" view="normal" rollover="" rollover_from="30" rollover_to="14" includeholiday="true"">Welcome!</span> 2096 <span style='font-weight:800;'>Service <i class="fal fa-clock"></i></span> 2097 <span data-fetch-shortcode data-code="mbhi_hours" data-arguments="location="Service" format="12" display="table" output="1" includeholidays="true" includevacations="" abbreviatedays="" consolidationseparator=" - " hourseparator=" - " entryseparator=", " mhbr="1" showonlytoday="" dayentryseparator=" " removezeroes="1" seo="" for_admin="" hide_hours="" startonsunday="" extra_classes="" dates_in_past="1" replace_with_specials="true" replace_with_vacations="" date_format="day first" replaced_vacations_format="{day} ({name})" replaced_specials_format="{day} *({month_short} {day_of_month})" included_vacations_format="{from_day_of_month} {from_month_short} - {to_day_of_month} {to_month_short}" included_specials_format="{day_of_month} {month_short}" day_format="{day}" view="normal" rollover="" rollover_from="30" rollover_to="14" includeholiday="true"">Welcome!</span> 2098 <span style='font-weight:800;'>Parts <i class="fal fa-clock"></i></span> 2099 <span data-fetch-shortcode data-code="mbhi_hours" data-arguments="location="Parts" format="12" display="table" output="1" includeholidays="true" includevacations="" abbreviatedays="" consolidationseparator=" - " hourseparator=" - " entryseparator=", " mhbr="1" showonlytoday="" dayentryseparator=" " removezeroes="1" seo="" for_admin="" hide_hours="" startonsunday="" extra_classes="" dates_in_past="1" replace_with_specials="true" replace_with_vacations="" date_format="day first" replaced_vacations_format="{day} ({name})" replaced_specials_format="{day} *({month_short} {day_of_month})" included_vacations_format="{from_day_of_month} {from_month_short} - {to_day_of_month} {to_month_short}" included_specials_format="{day_of_month} {month_short}" day_format="{day}" view="normal" rollover="" rollover_from="30" rollover_to="14" includeholiday="true"">Welcome!</span> 2100 <!--<span style='font-weight:800;'>Collison <i class="fal fa-clock"></i></span> 2101 [mbhi_hours location="Collision" display="table" includeholiday="true" replace_with_specials="true"]--> 2102 <span style='font-weight:800;'>Rental <i class="fal fa-clock"></i></span> 2103 <span data-fetch-shortcode data-code="mbhi_hours" data-arguments="location="Rental" format="12" display="table" output="1" includeholidays="true" includevacations="" abbreviatedays="" consolidationseparator=" - " hourseparator=" - " entryseparator=", " mhbr="1" showonlytoday="" dayentryseparator=" " removezeroes="1" seo="" for_admin="" hide_hours="" startonsunday="" extra_classes="" dates_in_past="1" replace_with_specials="true" replace_with_vacations="" date_format="day first" replaced_vacations_format="{day} ({name})" replaced_specials_format="{day} *({month_short} {day_of_month})" included_vacations_format="{from_day_of_month} {from_month_short} - {to_day_of_month} {to_month_short}" included_specials_format="{day_of_month} {month_short}" day_format="{day}" view="normal" rollover="" rollover_from="30" rollover_to="14" includeholiday="true"">Welcome!</span> 2104 </li> 2105</ul> </div>
2106 </div> 2107 </li> 2108 </ul> 2109 </div> 2110</div>
2111<script> 2112var CloseMenu = function(e) { 2113 $('.nav-below-btn-toggle').each(function() { 2114 if ($(this).hasClass('open')) { 2115 $(this).removeClass('open'); 2116 } else { 2117 2118 $(this).addClass('open'); 2119 } 2120 }); 2121 if ($('.dv-header-lower').length) { 2122 $('.dv-header-lower').toggleClass("dv-header-lower-closed"); 2123 } 2124 $(".dv-fw-search").toggleClass("dv-toggle-open"); 2125 $("body").toggleClass("mobile-menu-open"); 2126 $('#the-nav-below').remove(); 2127}; 2128$(function() { 2129 2130 // Icon Click FN 2131 $(".nav-below-btn-toggle").click(function(event) { 2132 event.preventDefault(); 2133 event.stopPropagation(); 2134 var lowerHeaderHeight = document.querySelector(".srp_main .dv-header-lower"); 2135 if(!!lowerHeaderHeight) { 2136 $(window).scroll(function() { 2137 var scroll = $(window).scrollTop(); 2138 var totalHeaderHeight = parseInt('75px', 10 ) - parseInt(lowerHeaderHeight.offsetHeight, 10 ) + 'px'; 2139 if (scroll > 0) { 2140 document.querySelector(".dv-fw-search").style.top = parseInt(totalHeaderHeight, 10) + parseInt(lowerHeaderHeight.offsetHeight, 10) + 'px'; 2141 } else { 2142 document.querySelector(".dv-fw-search").style.top = 'auto'; 2143 } 2144 }); 2145 } 2146 CloseMenu($(this)); 2147 }); 2148 2149 $(document).on('click', function(e) { 2150 var opened = $('body').hasClass('mobile-menu-open'); 2151 var bodyContent = $('body.mobile-menu-open'); 2152 var target = $(e.target); 2153 if (opened === true && target.is(bodyContent)) { 2154 CloseMenu($('.nav-below-btn-toggle')); 2155 } 2156 }); 2157 2158 // Open Dropdown Menu Mobile 2159 $(".dv-mobile-menu-inner #menu-mobile-menu > li.has-sub > a").click(function() { 2160 $(".dv-mobile-menu-inner #menu-mobile-menu > li.has-sub > a").parent().find("ul").slideUp("fast"); 2161 2162 var panel = this.nextElementSibling; 2163 panel.style.maxHeight = panel.style.maxHeight ? panel.scrollHeight : null; 2164 var curHeight = document.querySelector(".dv-mobile-menu-inner").style.height; 2165 curHeight = parseInt(curHeight, 10); 2166 2167 if ($(this).parent().hasClass("open-active")) { 2168 $(".dv-mobile-menu-inner #menu-mobile-menu > li.has-sub > a").parent().removeClass("open-active"); 2169 $(this).parent().find("ul").slideUp("fast"); 2170 2171 document.querySelector(".dv-mobile-menu-inner").style.height = curHeight - panel.scrollHeight + 'px'; 2172 } else { 2173 $(".dv-mobile-menu-inner #menu-mobile-menu > li.has-sub > a").parent().removeClass("open-active"); 2174 $(this).parent().toggleClass("open-active"); 2175 $(this).parent().find("ul").slideToggle("fast"); 2176 2177 document.querySelector(".dv-mobile-menu-inner").style.height = curHeight + panel.scrollHeight + 'px'; 2178 } 2179 2180 this.scrollIntoView(); 2181 }); 2182 2183 // Mobile Menu Selector 2184 $(".dv-fw-mobile-menu-selector li").on("click", function() { 2185 $(".dv-fw-mobile-menu-selector li").removeClass("active"); 2186 $(this).toggleClass("active"); 2187 var idx = $(this).index(); 2188 $(this).parents().find('.dv-fw-mobile-menu-item-content').removeClass('active'); 2189 $(this).parents().find('.dv-fw-mobile-menu-item-content').eq(idx).addClass('active') 2190 }); 2191 2192 // Mobile Menu Caret 2193 $(".dv-mobile-menu-inner #menu-mobile-menu li.has-sub > a").append('<span class="dv-mobile-menu-caret"><i class="fa fa-chevron-down"></i></span>'); 2194}); 2195 2196// Mobile fix for height of menu items 2197document.addEventListener("DOMContentLoaded", function() { 2198 var elmInnerHeight = document.querySelector(".dv-mobile-menu-inner").getBoundingClientRect().height; 2199 // var header = document.querySelector("header"); 2200 // var headerHeight = header.getBoundingClientRect().height; 2201 // var distanceToTop = header.getBoundingClientRect().top; 2202 var setHeight = Math.ceil((elmInnerHeight)).toString(); 2203 document.querySelector(".dv-mobile-menu-inner").style.height = setHeight + 'px'; 2204}); 2205</script>
2205 2206 2207<div class="bread-crumbs"> 2208 <div class="dv-bread-crumbs" style="display:none;" itemscope itemtype="https://schema.org/BreadcrumbList"><span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><a href="https://www.hubertvestertoyota.com" itemprop="item"><span itemprop="name"></span></a><meta itemprop="position" content="1"></span><span class="separator"> / </span><span itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem"><span itemprop="name">New Vehicles</span><meta itemprop="position" content="1"></span></div></div> 2209 2210<!-- da-srp-studio: switch=OFF (enable Redux → Integrations → SRP Functions → SRP Studio Config, then save options) studio=off (legacy Redux template) | clear cache: append ?srp_config_flush=1 --> 2211 <div class="srpLoading"> 2212 <div class="lds-ring"><div></div><div></div><div></div><div></div></div> 2213 </div> 2214 2215<div class="srp-header"> 2216 <div id="resultsStats"></div> 2217 <div class="srp-header-results"> 2218 <div class="srp-search"> 2219 <div class="srp-searchbar"> 2220 <i class="fas fa-search"></i> 2221 <div id="searchbox"></div> 2222 </div> 2223 <div id="clearSearchResults"><button><i class="fal fa-backspace"></i> <span>Clear<br>Search</span></button></div> 2224 </div> 2225 <div class="srp-header-right"> 2226 <div class="sortFilters" id="sortByDesktop"><div class="dv-srp-search-options-wrapper"><span class="dv-srp-search-options-label"><i class="fas fa-sort-amount-up"></i> <span class="dv-srp-search-options-dynamic-label">Sort</span></span></div></div> 2227 <div id="pagination-top"></div> 2228 </div> 2229 </div> 2230 <div class="dv-srp-search-options"> 2231 <div class="sortFilters" id="sortByMobile"><div class="dv-srp-search-options-wrapper"><span class="dv-srp-search-options-label"><i class="fas fa-sort-amount-up"></i> <span class="dv-srp-search-options-dynamic-label">Sort</span></span></div></div> 2232 <div class="showFiltersNonLegacy" id="showFiltersNonLegacy"></div> 2233 <div class="saveFilters"><div class="dv-srp-search-options-wrapper"><span class="dv-srp-search-options-label"><i class="fal fa-heart"></i> Save</span></div></div> 2234 </div> 2235</div> 2236 2237 2238<main> 2239 <div class="side-panel-container"> 2240 <section id="srp-filters" class="srp-filters"> 2241 <div class="srp-filters-close-wrapper"> 2242 <div class="srp-filters-reset-btn-wrapper"> 2243 <div id="srp-filters-reset-btn"></div> 2244 </div> 2245 <div class="srp-filters-close-btn"> 2246 <i class="fal fa-times"></i> Close 2247 </div> 2248 </div> 2249 <div class="range-slider-container srp-panel-toggle"> <div> 2250 <span> 2251 <h4>Price</h4> 2252 </span> 2253 <div id="price-range-slider"></div> 2254 </div> 2255 </div> 2256 2257 <div class="type-container srp-panel-toggle"> 2258 <span> 2259 <h4>Type</h4> 2260 </span> 2261 <div id="type-list"></div> 2262 </div> 2263 2264 <div class="dealertag-container srp-panel-toggle hidden-filter"> 2265 <span> 2266 <h4>Dealer Special</h4> 2267 <a><i class="far fa-chevron-up"></i></a> 2268 </span> 2269 <div id="dealertag-list"></div> 2270 </div> 2271 2272 <div class="make-container srp-panel-toggle"> 2273 <span> 2274 <h4>Make</h4> 2275 <a><i class="far fa-chevron-up"></i></a> 2276 </span> 2277 <div id="make-list"></div> 2278 </div> 2279 2280 <div class="modelCategory-container srp-panel-toggle"> 2281 <span> 2282 <h4>Model</h4> 2283 <a><i class="far fa-chevron-up"></i></a> 2284 </span> 2285 <div id="modelCategory-list"></div> 2286 </div> 2287 2288 <div class="trim-container srp-panel-toggle"> 2289 <span> 2290 <h4>Trim</h4> 2291 <a><i class="far fa-chevron-up"></i></a> 2292 </span> 2293 <div id="trim-list"></div> 2294 </div> 2295 2296 <div class="year-container srp-panel-toggle"> 2297 <span> 2298 <h4>Year</h4> 2299 <a><i class="far fa-chevron-up"></i></a> 2300 </span> 2301 <div id="year-list"></div> 2302 </div> 2303 2304 <div class="pricerange-container srp-panel-toggle"> 2305 <span> 2306 <h4>Price Range</h4> 2307 <a><i class="far fa-chevron-up"></i></a> 2308 </span> 2309 <div id="pricerange-list"></div> 2310 </div> 2311 2312 <div class="body-container srp-panel-toggle"> 2313 <span> 2314 <h4>Body</h4> 2315 <a><i class="far fa-chevron-up"></i></a> 2316 </span> 2317 <div id="body-list"></div>
2318 </div> 2319 2320 <div class="cab-container srp-panel-toggle"> 2321 <span> 2322 <h4>Cab Style</h4> 2323 <a><i class="far fa-chevron-up"></i></a> 2324 </span> 2325 <div id="cab-list"></div> 2326 </div> 2327 2328 <div class="bed-container srp-panel-toggle"> 2329 <span> 2330 <h4>Bed Style</h4> 2331 <a><i class="far fa-chevron-up"></i></a> 2332 </span> 2333 <div id="bed-list"></div> 2334 </div> 2335 2336 <div class="fuel-container srp-panel-toggle"> 2337 <span> 2338 <h4>Fuel</h4> 2339 <a><i class="far fa-chevron-up"></i></a> 2340 </span> 2341 <div id="fuel-list"></div> 2342 </div> 2343 2344 <div class="transmission-container srp-panel-toggle"> 2345 <span> 2346 <h4>Transmission</h4> 2347 <a><i class="far fa-chevron-up"></i></a> 2348 </span> 2349 <div id="transmission-list"></div> 2350 </div> 2351 2352 <div class="color-container srp-panel-toggle"> 2353 <span> 2354 <h4>Color</h4> 2355 <a><i class="far fa-chevron-up"></i></a> 2356 </span> 2357 <div id="color-list"></div> 2358 </div> 2359 2360 <div class="drivetrain-container srp-panel-toggle"> 2361 <span> 2362 <h4>Drivetrain</h4> 2363 <a><i class="far fa-chevron-up"></i></a> 2364 </span> 2365 <div id="drivetrain-list"></div> 2366 </div> 2367 2368 <div class="location-container srp-panel-toggle"> 2369 <span> 2370 <h4>Location</h4> 2371 <a><i class="far fa-chevron-up"></i></a> 2372 </span> 2373 <div id="location-list"></div> 2374 </div> 2375 2376 <div class="mpg-hway-container srp-panel-toggle"> 2377 <span> 2378 <h4>MPG Highway</h4> 2379 <a><i class="far fa-chevron-up"></i></a> 2380 </span> 2381 <div id="mpg-hway-list"></div> 2382 </div> 2383 2384 <div class="mpg-city-container srp-panel-toggle"> 2385 <span> 2386 <h4>MPG City</h4> 2387 <a><i class="far fa-chevron-up"></i></a> 2388 </span> 2389 <div id="mpg-city-list"></div> 2390 </div> 2391 2392 <div class="features-container srp-panel-toggle"> 2393 <span> 2394 <h4>Features</h4> 2395 <a><i class="far fa-chevron-up"></i></a> 2396 </span> 2397 <div id="features-list"></div> 2398 </div> 2399 2400 <div class="status-container srp-panel-toggle"> 2401 <span> 2402 <h4>Status</h4> 2403 <a><i class="far fa-chevron-up"></i></a> 2404 </span> 2405 <div id="status-list"></div> 2406 </div> 2407 2408 <div class="range-container srp-panel-toggle"> 2409 <span> 2410 <h4>Range</h4> 2411 <a><i class="far fa-chevron-up"></i></a> 2412 </span> 2413 <div id="range-list"></div> 2414 </div> 2415 2416 </section> 2417</div> 2418 2419<div class="filterResultCount"><span id="srpFilterResultCount"></span></div> 2420 2421<div class="result-wrapper "> 2422 2423 <h1 style="visibility: hidden; position: absolute; z-index: 0;">New Vehicles</h1> 2424 2425 2426 <div class="ag-tp-trade-srp-banner"></div> 2427 <div class="ag-tp-payments-srp-banner"></div> 2428 <div class="ag-tp-qualified-srp-banner"></div> 2429 2430 <div class="dv-srp-filter-tags"> 2431 <div class="dv-srp-filter-clear-btn" id="dv-srp-clear-filters"></div> 2432 <div id="filterTags"></div> 2433 </div> 2434 2435 <div id="srp-results" class="srp-results"> 2436 <div id="hit-template"> 2437 <div> 2438 <div class="listing" data-vehicle-id="{{databaseID}}" data-vehicle-vin="{{vin}}" data-vehicle-condition="{{condition}}" data-vehicle-year="{{yr}}" data-vehicle-stock-number="{{stockNumber}}" data-vehicle-make-model="{{make}} {{model}}" data-vehicle-price="{{final_price}}" data-vehicle-discount="{{discount_matrix}}" data-dealer-name="{{dealer.name}}" data-ag-ext-color="{{exteriorColor}}" data-ag-price="{{finalPriceInt}}" data-ag-make="{{make}}" data-ag-model="{{model}}" data-ag-type="{{body}}" data-ag-trim="{{trim}}" data-ag-vdp-url="{{vdpUrl}}"> 2439 <div class="listing-container" data-url='{{vdpUrl}}'> 2440 <div class="left-side"> 2441 {{#flags.hasSoldVehicles}} 2442 <div class="srp-mc-sold-banner"> 2443 <p>SOLD</p> 2444 </div> 2445 {{/flags.hasSoldVehicles}} 2446 <div class="vehicle-image"> 2447 2448 <div class="img-container image-ratio-perc image-aspect-ratio-4x3"> 2449 {{#flags.hasSpecial}} 2450 <div class="vehicle-special srp-banner-overlay">{{flags.specialText}}</div> 2451 {{/flags.hasSpecial}} 2452 {{#flags.isReserved}} 2453 <div class="vehicle-special reserved-vehicle"> 2454 This vehicle has a pending sale. <div class="dv-tooltip"> 2455 <p class="dv-tooltip-content">Pending Sale indicates a customer has either reserved or has begun the process to purchase this vehicle. Please contact us directly to learn about similar vehicles.</p> 2456 <i class="fal fa-question-circle"></i> 2457 </div> 2458 </div> 2459 {{/flags.isReserved}} 2460 <div class="vehicle-views"> 2461 <!-- Current image carousel --> 2462 <div id="swiper-323182" class="swiper srp-swiper-vehicles img" data-id="323182"> 2463 <div class="swiper-wrapper"> 2464 {{#imageUrls}} 2465 <div class="swiper-slide"> 2466 <img class="lazy srp-click-image" alt="{{condition}} {{yr}} {{make}} {{model}} {{body}}" data-src="{{.}}" /> 2467 <div class="swiper-lazy-preloader"></div> 2468 </div> 2469 {{/imageUrls}} 2470 </div> 2471 <!-- Add Navigation --> 2472 <!-- Changed <div> to <button> to prevent rapid clicks from triggering native text-selection/highlight on SRP cards --> 2473 <button type="button" class="swiper-button-next swiper-button-next-323182" aria-label="Next slide"></button> 2474 <button type="button" class="swiper-button-prev swiper-button-prev-323182" aria-label="Previous slide"></button> 2475</div> </div> 2476 </div> 2477 2478 <div class="dv-smartpath-container"> 2479 {{#flags.hasSmartpathDisclaimer}} 2480 <div class="dv-smartpath-disclaimer"> 2481 <p class="dv-sp-disclaimer">{{smartpathDisclaimer}}</p> 2482 </div> 2483 {{/flags.hasSmartpathDisclaimer}} 2484 </div> 2485 <div class="vehicle-colors"> 2486 <div class="exterior-color">
2487 {{#exteriorColor}} 2488 {{#exteriorHex}} 2489 <div style="background-color:{{exteriorHex}};"></div> 2490 {{/exteriorHex}} 2491 {{^exteriorHex}} 2492 {{#genericColor}} 2493 <div style="background-color:{{genericColor}};"></div> 2494 {{/genericColor}} 2495 {{^genericColor}} 2496 <div style="background: url('//bucket.dealeralchemist.com/assets/images/slash-square.png');background-size: 100%;"></div> 2497 {{/genericColor}} 2498 {{/exteriorHex}} 2499 <div class="color-info"> 2500 <p class="color-label">EXTERIOR</p> 2501 <p class="color">{{exteriorColor}} {{#exteriorColorDisclaimer}}<i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-disclaimer="{{exteriorColorDisclaimer}}"></i>{{/exteriorColorDisclaimer}}</p> 2502 </div> 2503 {{/exteriorColor}} 2504 </div> 2505 <div class="interior-color"> 2506 {{#interiorColor}} 2507 {{#interiorHex}} 2508 <div style="background-color:{{interiorHex}};"></div> 2509 {{/interiorHex}} 2510 {{^interiorHex}} 2511 {{#genericInteriorColor}} 2512 <div style="background-color:{{genericInteriorColor}};"></div> 2513 {{/genericInteriorColor}} 2514 {{^genericInteriorColor}} 2515 <div style="background: url('//bucket.dealeralchemist.com/assets/images/slash-square.png');background-size: 100%;"></div> 2516 {{/genericInteriorColor}} 2517 {{/interiorHex}} 2518 <div class="color-info"> 2519 <p class="color-label">INTERIOR</p> 2520 <p class="color">{{interiorColor}} {{#interiorColorDisclaimer}}<i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-disclaimer="{{interiorColorDisclaimer}}"></i>{{/interiorColorDisclaimer}}</p> 2521 </div> 2522 {{/interiorColor}} 2523 </div> 2524 </div> 2525 2526 </div> 2527 </div> 2528 <div class="right-side"> 2529 <div class="right-top" style="padding-left:0px"> 2530 <div class="vehicle-info"> 2531 <div class="vehicle-title-wrap"> 2532 <a href="{{vdpUrl}}"> 2533 <h2 class="car-title"><p class="category">{{condition}} {{yr}}</p> 2534<span class="new-used secondary_color">{{make}} {{model}} {{trim}} {{cab}} {{bed}}</span></h2> 2535 <div class="vin-stock"> 2536 <p class="vin">{{#mileage}}<div class='ag-srp-miles'><p style='font-size:12px;'><i class="fa-light fa-gauge-low"></i> Mileage <span style='font-size:12px;'>{{#helpers.formatNumber}}{{mileage}}{{/helpers.formatNumber}} </span></p></div>{{/mileage}}</p> 2537 </div> 2538 </a> 2539 <div class="title-actions"> 2540 </div> 2541 </div> 2542 <div class="specs"> 2543 <!--<p>Engine <span style="font-weight: bold;font-family: 'ToyotaType', sans-serif">{{engine}}</span></p> 2544<p>Drivetrain <span style="font-weight: bold;font-family: 'ToyotaType', sans-serif">{{drivetrain}}</span></p> 2545{{#range}}<p>Range <span style="font-weight: bold;font-family: 'ToyotaType', sans-serif">{{range}}</span></p>{{/range}} 2546--> 2547<div class="man-badges"> 2548{{#flags.hasToyotaCare}} 2549 <a href="/toyotacare/" class="dv-tooltip"><p class="dv-tooltip-content">ToyotaCare is a no cost maintenance plan with 24-hour roadside assistance. The ToyotaCare plan covers normal factory scheduled maintenance for 2 years or 25,000 miles, whichever comes first. 24-hour roadside assistance is also included for 2 years and unlimited miles.</p><img alt="toyota care logo" src="//bucket.dealervenom.com/assets/oem/toyota/logos/toyota-care.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=100"></a> 2550{{/flags.hasToyotaCare}} 2551{{#flags.hasToyotaSafety}} 2552 <a href="/toyota-safety-sense/" class="dv-tooltip dv-toyota-safety-sense"><p class="dv-tooltip-content">Toyota Safety Sense™ (TSS) is a bundle of active safety features included on many new Toyota vehicles at no additional cost. These innovative features were designed to help protect you and your passengers from harm.</p><img alt="toyota safety sense logo" src="//bucket.dealervenom.com/assets/oem/toyota/logos/toyota-safety-sense.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=56"></a> 2553{{/flags.hasToyotaSafety}} 2554</div> </div> 2555 </div> 2556 {{#certified}} 2557 <div class="srp-tcuv-container"> 2558 <img src="https://media.dealeralchemist.com/oem/toyota/logo-certified-used-vehicles.svg?auto=compress%2Cformat" alt="TCUV Logo" width="50%"/> 2559 {{#flags.isGoldCertified}} 2560 <div class="srp-tcuv-gold">
2561 <span>GOLD CERTIFIED</span> 2562 <p>View Details <a href="/certified-vehicle-information/" target="_blank"><i class="fad fa-info-circle"></i></a></p> 2563 </div> 2564 {{/flags.isGoldCertified}} 2565 {{#flags.isSilverCertified}} 2566 <div class="srp-tcuv-silver"> 2567 <span>SILVER CERTIFIED</span> 2568 <p>View Details <a href="/certified-vehicle-information/" target="_blank"><i class="fad fa-info-circle"></i></a></p> 2569 </div> 2570 {{/flags.isSilverCertified}} 2571 </div> 2572 {{/certified}} 2573 <div class="vehicle-price-container"> 2574 <div class="vehicle-price flex_box"> 2575 {{!-- ============================================================ --}} 2576{{!-- SRP PRICING STACK --}} 2577{{!-- Renders pricing breakdown for vehicle search result cards. --}} 2578{{!-- ============================================================ --}} 2579{{^flags.internetPriceHigher}} 2580 {{#flags.msrpFinal}} 2581 {{#flags.noFinalPrice}} 2582 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2583 <p class="dv-pricing-stack-strong"> 2584 <a data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales" href='tel:{{dealer.phone}}'>CALL FOR PRICE</a> 2585 <span class="dv-pricing-stack-value-default"> 2586 <a data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales" href='tel:{{dealer.phone}}'>{{dealer.phone}}</a> 2587 </span> 2588 </p> 2589 </div> 2590 {{/flags.noFinalPrice}} 2591 {{^flags.noFinalPrice}} 2592 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2593 <p class="dv-pricing-stack-strong"> 2594 TSRP 2595 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="MSRP" data-disclaimer="This is the Manufacturer Suggested Retail Price for this Vehicle."></i> 2596 2597 <span class="dv-pricing-stack-strong">{{msrp}}</span> 2598 </p> 2599 </div> 2600 {{/flags.noFinalPrice}} 2601 {{/flags.msrpFinal}} 2602 {{^flags.msrpFinal}} 2603 <div class="dv-pricing-stack-container"> 2604 {{#flags.noFinalPrice}} 2605 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2606 <p class="dv-pricing-stack-strong"> 2607 <a data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales" href='tel:{{dealer.phone}}'>CALL FOR PRICE</a> 2608 <span class="dv-pricing-stack-value-default"> 2609 <a data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales" href='tel:{{dealer.phone}}'>{{dealer.phone}}</a> 2610 </span> 2611 </p> 2612 </div> 2613 {{/flags.noFinalPrice}} 2614 {{^flags.noFinalPrice}} 2615 2616 {{!-- ── MSRP (with strikethrough slash) ── --}} 2617 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2618 <p class="dv-pricing-stack-strong"> 2619 TSRP 2620 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="MSRP" data-disclaimer="This is the Manufacturer Suggested Retail Price for this Vehicle."></i> 2621 2622 <span class="dv-pricing-stack-strong">{{msrp}}</span> 2623 </p> 2624 </div> 2625 2626 {{!-- ── Custom Pricing Rule (Dealer Adjustment) ── --}} 2627 {{#flags.hasDiscountMatrix}} 2628 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2629 <p class="dv-pricing-stack-strong"> 2630 Dealer Adjustment 2631 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-disclaimer="This is a custom dealer amount."></i> 2632 <span class="dv-pricing-stack-strong">{{discountMatrix}}</span> 2633 </p> 2634 </div> 2635 {{/flags.hasDiscountMatrix}} 2636 {{!-- ── Dealer Doc Fees ── --}} 2637 {{#flags.hasDealerFees}} 2638 {{#dealerFees}} 2639 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2640 <p class="dv-pricing-stack-strong">{{name}} <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="{{name}}" data-disclaimer="{{disclaimer}}"></i>
2641 <span class="dv-pricing-stack-strong">+{{displayAmount}}</span> 2642 </p> 2643 </div> 2644 {{/dealerFees}} 2645 {{/flags.hasDealerFees}} 2646 2647 {{!-- ── Dealer Installed Accessories ── --}} 2648 {{#options}} 2649 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2650 <p class="dv-pricing-stack-strong"> 2651 {{name}} 2652 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="Dealer Installed Options" data-disclaimer="Installed Packages by the Dealership. {{name}} - {{description}}"></i> 2653 <span class="dv-pricing-stack-strong">+{{price}}</span> 2654 </p> 2655 </div> 2656 {{/options}} 2657 2658 {{!-- ── Non-Conditional Incentives (with flyout) ── --}} 2659 {{#flags.hasIncentives}} 2660 <div class="ag-incentives-row-wrap"> 2661 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2662 <p class="dv-pricing-stack-strong"> 2663 {{make}} Incentives 2664 <i class="fad fa-info-circle ag-incentives-icon-trigger" tabindex="0" role="button" aria-label="View incentive details"></i> 2665 <span class="dv-pricing-stack-strong">{{incentivesDiscount}}</span> 2666 </p> 2667 </div> 2668 <div class="ag-conditional-offers ag-incentives-flyout"> 2669 <details class="ag-details-wrapper"> 2670 <summary class="ag-incentives-hidden-summary" aria-hidden="true"></summary> 2671 <div class="ag-conditional-panel"> 2672 <div class="ag-conditional-panel-inner"> 2673 {{#incentives}} 2674 <div class="dv-dealer-subtotal da-srp-incentive-stack dv-pricing-main"> 2675 <div class="ag-incentive-line-item"> 2676 <p class="da-srp-incentive da-conditional ag-incentive-row"> 2677 <span class="ag-incentive-copy-wrap"> 2678 <span class="ag-incentive-title">{{programDescription}}</span> 2679 <span class="ag-incentive-disclaimer">{{disclaimerText}}</span> 2680 </span> 2681 <span class="da-conditional ag-incentive-value">-{{programValue}}</span> 2682 </p> 2683 </div> 2684 </div> 2685 {{/incentives}} 2686 {{^flags.hasIncentives}} 2687 <div class="ag-dealer-cond-incentive"> 2688 <p class="ag-pricing-stack-desc">No incentive details available at this time.</p> 2689 </div> 2690 {{/flags.hasIncentives}} 2691 </div> 2692 </div> 2693 </details> 2694 </div> 2695 </div> 2696 {{/flags.hasIncentives}} 2697 2698 {{!-- ── Dealer / Feed Discount ── --}} 2699 {{#flags.hasDealerDiscount}} 2700 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2701 <p class="dv-pricing-stack-strong"> 2702 Dealer Discount 2703 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="Dealer Discount" data-disclaimer="This is the discount provided by the dealership."></i> 2704 <span class="dv-pricing-stack-strong">{{dealerDiscount}}</span> 2705 </p> 2706 </div> 2707 {{/flags.hasDealerDiscount}} 2708 2709 2710 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2711 <p class="dv-pricing-stack-strong"> 2712 Our Price 2713 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="Our Price" data-disclaimer="This is our price after all discounts and incentives everyone qualifies for."></i> 2714 <span class="dv-pricing-stack-value-default" style="color: #00BB00 !important;">{{finalPrice}}</span> 2715 </p> 2716 </div> 2717 {{/flags.noFinalPrice}} 2718 </div> 2719 {{/flags.msrpFinal}} 2720{{/flags.internetPriceHigher}} 2721{{#flags.internetPriceHigher}} 2722 {{^flags.noFinalPrice}} 2723 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2724 <p class="dv-pricing-stack-strong"> 2725 MSRP 2726 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="MSRP" data-disclaimer="This is the Manufacturer Suggested Retail Price for this Vehicle."></i> 2727 2728 <span class="dv-pricing-stack-strong">{{msrp}}</span> 2729 </p> 2730 </div> 2731 {{!-- ── Dealer Doc Fees ── --}} 2732 {{#flags.hasDealerFees}} 2733 {{#dealerFees}} 2734 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2735 <p class="dv-pricing-stack-strong">{{name}} <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="{{name}}" data-disclaimer="{{disclaimer}}"></i> 2736 <span class="dv-pricing-stack-strong">+{{displayAmount}}</span> 2737 </p> 2738 </div> 2739 {{/dealerFees}} 2740 {{/flags.hasDealerFees}} 2741 <div class="dv-dealer-subtotal dv-price-stack dv-pricing-main"> 2742 <p class="dv-pricing-stack-strong"> 2743 Our Price 2744 <i class="fad fa-info-circle" onclick="DVPopUp(this);return false;" data-modal-title="Our Price" data-disclaimer="This is our price after all discounts and incentives everyone qualifies for."></i>
2745 <span class="dv-pricing-stack-value-default" style="color: #00BB00 !important;">{{finalPrice}}</span> 2746 </p> 2747 </div> 2748 {{/flags.noFinalPrice}} 2749{{/flags.internetPriceHigher}} 2750 2751{{!-- ============================================================ --}} 2752{{!-- FLYOUT BEHAVIOR SCRIPT --}} 2753{{!-- Handles expand/collapse for incentives and doc-fee panels. --}} 2754{{!-- Self-initializing guard prevents double-binding. --}} 2755{{!-- ============================================================ --}}
2756<script> 2757(function () { 2758if (window.agOfferFlyoutsInitialized) return; 2759window.agOfferFlyoutsInitialized = true; 2760 2761const VEHICLE_CARD_SELECTOR = '.ag-vehicle-card, .vehicle-card, .inventory-card, .srp-vehicle, .vdp-vehicle, [data-vehicle]'; 2762const ANIMATION_DURATION = 250; 2763 2764/* ── Helpers ───────────────────────────────────────────── */ 2765 2766function getPriceContainer(element) { 2767const card = element.closest(VEHICLE_CARD_SELECTOR); 2768return card ? card.querySelector('.vehicle-price-container') : null; 2769} 2770 2771function expandFlyout(flyout, details, panel, priceContainer) { 2772details.open = true; 2773const pushAmount = panel.scrollHeight + 10; 2774 2775requestAnimationFrame(function () { 2776requestAnimationFrame(function () { 2777flyout.classList.add('ag-is-expanded'); 2778 2779if (priceContainer) { 2780priceContainer.style.transition = 'transform 250ms ease'; 2781priceContainer.style.transform = 'translateY(-' + pushAmount + 'px)'; 2782} 2783}); 2784}); 2785} 2786 2787function collapseFlyout(flyout, details, priceContainer) { 2788flyout.classList.remove('ag-is-expanded'); 2789 2790if (priceContainer) { 2791priceContainer.style.transform = ''; 2792} 2793 2794setTimeout(function () { 2795if (!flyout.classList.contains('ag-is-expanded')) { 2796details.open = false; 2797} 2798}, ANIMATION_DURATION); 2799} 2800 2801function toggleFlyout(flyout, details, panel, priceContainer) { 2802if (!flyout || !details || !panel) return; 2803 2804const isExpanding = !flyout.classList.contains('ag-is-expanded'); 2805 2806if (isExpanding) { 2807expandFlyout(flyout, details, panel, priceContainer); 2808} else { 2809collapseFlyout(flyout, details, priceContainer); 2810} 2811} 2812 2813/* ── Click Handler ─────────────────────────────────────── */ 2814 2815document.addEventListener('click', function (e) { 2816 2817/* Incentives icon trigger */ 2818const incentivesIconTrigger = e.target.closest('.ag-incentives-icon-trigger'); 2819if (incentivesIconTrigger) { 2820const wrap = incentivesIconTrigger.closest('.ag-incentives-row-wrap'); 2821if (!wrap) return; 2822 2823const flyout = wrap.querySelector('.ag-incentives-flyout'); 2824const details = wrap.querySelector('.ag-details-wrapper'); 2825const panel = wrap.querySelector('.ag-conditional-panel'); 2826const priceContainer = getPriceContainer(incentivesIconTrigger); 2827 2828e.preventDefault(); 2829e.stopPropagation(); 2830toggleFlyout(flyout, details, panel, priceContainer); 2831return; 2832} 2833 2834/* Doc fee icon trigger */ 2835const docFeeIconTrigger = e.target.closest('.ag-doc-fee-icon-trigger'); 2836if (docFeeIconTrigger) { 2837const wrap = docFeeIconTrigger.closest('.ag-doc-fee-row-wrap'); 2838if (!wrap) return; 2839 2840const flyout = wrap.querySelector('.ag-doc-fee-flyout'); 2841const details = wrap.querySelector('.ag-doc-fee-details-wrapper'); 2842const panel = wrap.querySelector('.ag-doc-fee-panel'); 2843const priceContainer = getPriceContainer(docFeeIconTrigger); 2844 2845e.preventDefault(); 2846e.stopPropagation(); 2847toggleFlyout(flyout, details, panel, priceContainer); 2848return; 2849} 2850 2851/* Close incentives flyout on outside click */ 2852const openIncentivesFlyout = document.querySelector('.ag-incentives-flyout.ag-is-expanded'); 2853if (openIncentivesFlyout) { 2854const wrap = openIncentivesFlyout.closest('.ag-incentives-row-wrap'); 2855if (wrap && !wrap.contains(e.target)) { 2856const details = openIncentivesFlyout.querySelector('.ag-details-wrapper'); 2857const priceContainer = getPriceContainer(openIncentivesFlyout); 2858if (details) collapseFlyout(openIncentivesFlyout, details, priceContainer); 2859} 2860} 2861 2862/* Close doc fee flyout on outside click */ 2863const openDocFeeFlyout = document.querySelector('.ag-doc-fee-flyout.ag-is-expanded'); 2864if (openDocFeeFlyout) { 2865const wrap = openDocFeeFlyout.closest('.ag-doc-fee-row-wrap'); 2866if (wrap && !wrap.contains(e.target)) { 2867const details = openDocFeeFlyout.querySelector('.ag-doc-fee-details-wrapper'); 2868const priceContainer = getPriceContainer(openDocFeeFlyout); 2869if (details) collapseFlyout(openDocFeeFlyout, details, priceContainer); 2870} 2871} 2872}); 2873 2874/* ── Keyboard Handler (Enter / Space) ──────────────────── */ 2875 2876document.addEventListener('keydown', function (e) { 2877if (e.key !== 'Enter' && e.key !== ' ') return; 2878 2879/* Incentives keyboard trigger */ 2880const incentivesKeyTrigger = e.target.closest('.ag-incentives-icon-trigger'); 2881if (incentivesKeyTrigger) { 2882const wrap = incentivesKeyTrigger.closest('.ag-incentives-row-wrap'); 2883if (!wrap) return; 2884 2885const flyout = wrap.querySelector('.ag-incentives-flyout'); 2886const details = wrap.querySelector('.ag-details-wrapper'); 2887const panel = wrap.querySelector('.ag-conditional-panel'); 2888const priceContainer = getPriceContainer(incentivesKeyTrigger); 2889 2890e.preventDefault(); 2891toggleFlyout(flyout, details, panel, priceContainer); 2892return; 2893} 2894 2895/* Doc fee keyboard trigger */ 2896const docFeeKeyTrigger = e.target.closest('.ag-doc-fee-icon-trigger'); 2897if (docFeeKeyTrigger) { 2898const wrap = docFeeKeyTrigger.closest('.ag-doc-fee-row-wrap'); 2899if (!wrap) return; 2900 2901const flyout = wrap.querySelector('.ag-doc-fee-flyout'); 2902const details = wrap.querySelector('.ag-doc-fee-details-wrapper'); 2903const panel = wrap.querySelector('.ag-doc-fee-panel'); 2904const priceContainer = getPriceContainer(docFeeKeyTrigger); 2905 2906e.preventDefault(); 2907toggleFlyout(flyout, details, panel, priceContainer); 2908} 2909}); 2910})(); 2911</script>
2911 2912 2913{{!-- ============================================================ --}} 2914{{!-- STYLES --}} 2915{{!-- ============================================================ --}} 2916<style> 2917 2918/* ── Price Stack ───────────────────────────────────────── */ 2919 2920.dv-price-stack p { 2921height: 23px; 2922font-size: 14px; 2923font-weight: bold; 2924position: relative; 2925} 2926 2927.dv-price-stack p b { 2928font-size: 14px; 2929font-weight: bold; 2930} 2931 2932.dv-price-stack span { 2933font-size: 14px; 2934font-weight: bold; 2935} 2936 2937.dv-price-stack .dv-price-slash { 2938max-width: 63px; 2939z-index: 98; 2940position: absolute; 2941right: 0; 2942} 2943 2944.dv-pricing-stack-strong .dv-pricing-stack-value-default { 2945color: #00bb00; 2946} 2947 2948 2949/* ── Incentives Flyout ─────────────────────────────────── */ 2950 2951.ag-incentives-row-wrap { 2952position: relative; 2953} 2954 2955.ag-incentives-hidden-summary { 2956display: none; 2957} 2958 2959.ag-incentives-icon-trigger { 2960cursor: pointer; 2961margin-left: 4px; 2962color: inherit; 2963} 2964 2965.ag-incentives-icon-trigger:focus-visible { 2966outline: 2px solid rgba(0, 0, 0, 0.18); 2967outline-offset: 2px; 2968border-radius: 2px; 2969} 2970 2971.ag-incentives-flyout { 2972width: 100%; 2973position: relative; 2974--anim-speed: 250ms; 2975margin-top: 0; 2976border-top: 0; 2977padding-top: 0; 2978} 2979 2980.ag-incentives-flyout .ag-conditional-panel { 2981display: grid; 2982grid-template-rows: 0fr; 2983position: absolute; 2984left: 0; 2985right: 0; 2986bottom: calc(100% + 10px); 2987overflow: hidden; 2988transition: grid-template-rows var(--anim-speed) ease; 2989border-radius: 10px; 2990background: rgba(255, 255, 255, 0.92); 2991backdrop-filter: blur(8px); 2992z-index: 999; 2993box-shadow: 0 10px 28px rgba(0, 0, 0, 0.16); 2994} 2995 2996.ag-incentives-flyout.ag-is-expanded .ag-conditional-panel { 2997grid-template-rows: 1fr; 2998border: 1px solid rgba(0, 0, 0, 0.08); 2999} 3000 3001.ag-incentives-flyout .ag-conditional-panel-inner { 3002min-height: 0; 3003padding: 0 14px; 3004transition: padding var(--anim-speed) ease; 3005} 3006 3007.ag-incentives-flyout.ag-is-expanded .ag-conditional-panel-inner { 3008padding: 12px 14px; 3009} 3010 3011.ag-incentives-flyout .da-srp-incentive-stack, 3012.ag-incentives-flyout .da-srp-incentive-stack .dv-pricing-stack-strong, 3013.ag-incentives-flyout .da-srp-incentive-stack p { 3014height: auto !important; 3015min-height: 0; 3016} 3017 3018 3019/* ── Doc Fee Flyout ────────────────────────────────────── */ 3020 3021.ag-doc-fee-row-wrap { 3022position: relative; 3023} 3024 3025.ag-doc-fee-hidden-summary { 3026display: none; 3027} 3028 3029.ag-doc-fee-icon-trigger { 3030cursor: pointer; 3031margin-left: 4px; 3032color: inherit; 3033} 3034 3035.ag-doc-fee-icon-trigger:focus-visible { 3036outline: 2px solid rgba(0, 0, 0, 0.18); 3037outline-offset: 2px; 3038border-radius: 2px; 3039} 3040 3041.ag-doc-fee-flyout { 3042width: 100%; 3043position: relative; 3044--anim-speed: 250ms; 3045margin-top: 0; 3046border-top: 0; 3047padding-top: 0; 3048} 3049 3050.ag-doc-fee-flyout .ag-doc-fee-panel { 3051display: grid; 3052grid-template-rows: 0fr; 3053position: absolute; 3054left: 0; 3055right: 0; 3056bottom: calc(100% + 10px); 3057overflow: hidden; 3058transition: grid-template-rows var(--anim-speed) ease; 3059border-radius: 10px; 3060background: rgba(255, 255, 255, 0.92); 3061backdrop-filter: blur(8px); 3062z-index: 999; 3063box-shadow: 0 10px 28px rgba(0, 0, 0, 0.16); 3064} 3065 3066.ag-doc-fee-flyout.ag-is-expanded .ag-doc-fee-panel { 3067grid-template-rows: 1fr; 3068border: 1px solid rgba(0, 0, 0, 0.08); 3069} 3070 3071.ag-doc-fee-flyout .ag-doc-fee-panel-inner { 3072min-height: 0; 3073padding: 0 14px; 3074transition: padding var(--anim-speed) ease; 3075} 3076 3077.ag-doc-fee-flyout.ag-is-expanded .ag-doc-fee-panel-inner { 3078padding: 12px 14px; 3079} 3080 3081.ag-doc-fee-flyout .da-srp-incentive-stack, 3082.ag-doc-fee-flyout .da-srp-incentive-stack .dv-pricing-stack-strong, 3083.ag-doc-fee-flyout .da-srp-incentive-stack p { 3084height: auto !important; 3085min-height: 0; 3086} 3087 3088 3089/* ── Shared Line Item Styles (used by both flyouts) ────── */ 3090 3091.ag-incentive-line-item { 3092width: 100%; 3093} 3094 3095.ag-incentive-row { 3096display: grid; 3097grid-template-columns: minmax(0, 1fr) auto; 3098align-items: start; 3099column-gap: 10px; 3100margin: 0; 3101line-height: 1.25; 3102} 3103 3104.ag-incentive-copy-wrap { 3105min-width: 0; 3106display: block; 3107} 3108 3109.ag-incentive-title { 3110display: block; 3111font-size: 0.8rem;
3112font-weight: 700; 3113color: #222; 3114line-height: 1.2; 3115} 3116 3117.ag-incentive-disclaimer { 3118display: block; 3119margin-top: 3px; 3120font-size: 0.55rem; 3121line-height: 1.25; 3122color: #666; 3123font-weight: 400; 3124white-space: normal; 3125overflow-wrap: anywhere; 3126} 3127 3128.ag-incentive-value { 3129display: inline-block; 3130white-space: nowrap; 3131font-size: 0.8rem !important; 3132font-weight: 700; 3133align-self: start; 3134} 3135 3136.da-srp-incentive-stack { 3137position: relative; 3138padding: 8px 0; 3139} 3140 3141.da-srp-incentive-stack:not(:last-child) { 3142border-bottom: 1px dashed #d7d7d7; 3143} 3144 3145.da-srp-incentive-stack:last-child { 3146border-bottom: none; 3147} 3148 3149.ag-details-wrapper summary::-webkit-details-marker, 3150.ag-doc-fee-details-wrapper summary::-webkit-details-marker { 3151display: none; 3152} 3153 3154.ag-details-wrapper summary, 3155.ag-doc-fee-details-wrapper summary { 3156list-style: none; 3157outline: none; 3158} 3159 3160</style> 3161 3162 </div> 3163 3164 3165 3166 3167 3168 3169 </div> 3170 3171 <!-- Conditional Incentives SRP card displays --> 3172 <!--END Conditional Incentives SRP card displays --> 3173 3174 3175 </div> 3176 3177 3178 3179 3180 <div class="right-bottom"> 3181 3182 <div class="srp-cta"> 3183 3184 3185 3186 <a href='javascript: void(0);' data-vehicle-id="{{databaseID}}" data-vehicle-vin="{{vin}}" data-vehicle-year="{{yr}}" data-vehicle-stock-number="{{stockNumber}}" data-vehicle-make-model="{{make}} {{model}}" data-vehicle-price="{{final_price}}" data-vehicle-discount="{{discount_matrix}}" data-dealer-name="{{dealer.name}}" class="srp-cta-1-btn srp_cta_1 srp_cta">Value Your Trade <span style="display:none;" class="vehicle_title_form">{{yr}} {{make}} {{model}} </span> 3187 </a> 3188 <div class="srp-extra-div"><p class="trans" style="color:#838383;font-size:.65rem;">VIN: <span class="bold-value-2" style="color:#838383; font-size:.65rem; font-weight: 600;"> {{vin}}</span></p> 3189{{#stockNumber}}<p class="trim" style="color:#838383;font-size:.65rem;">Stock:<span class="bold-value-2" style="color:#838383; font-size:.65rem; font-weight: 600;"> {{stockNumber}}</span></p>{{/stockNumber}}</div> 3190 </div> 3191 <!--End .srp-cta--> 3192 </div> 3193 </div> 3194 3195 </div> 3196 3197 3198 <div class="listing-bottom-row srp-lower-bar"> 3199 <div class="dealer-phone"> 3200 <p style="text-transform: capitalize;"><a data-aga-event="getDirections" href="{{dealer.googleShareUrl}}" target="_blank">{{dealer.name}}</a></p> 3201 <p><a class="dv-lowerbar-used-srp-veh-phone" data-aga-event="clickToCall" data-aga-event-set-prop="clickToCallDepartment|Sales" href="tel:{{dealer.phone}}"><i class="fal fa-phone-alt"></i>{{dealer.phone}}</a></p> 3202</div> </div> 3203 </div> 3204 </div> 3205 </div> 3206 </div> 3207 3208 3209 <div class="srp-footer"> 3210 <div id="resultsStats-bottom"></div> 3211 <div id="pagination-bottom"></div> 3212 </div> 3213</div> 3214 3215<div id="empty-template" style='display:none;'> 3216 <div class='row srp-no-results'><h3>Don't see the vehicle you are looking for? We will find it for you!</h3></div><div class='srp-noResults-wrapper'> 3217 <div class='gf_browser_chrome gform_wrapper orderparts_wrapper' id='gform_wrapper_7' ><form data-id="7" data-type="consumer_contact" data-department="sales" data-name="Vehicle Finder Service" data-redirected="true" method='post' enctype='multipart/form-data' id='gform_7' class='orderparts' action='/new-vehicles/?make=Toyota&model=Tacoma+i-FORCE+MAX'> 3218 <div class='gform_body'><ul id='gform_fields_7' class='gform_fields left_label form_sublabel_below description_below'><li id='field_7_6' class='gfield gsection field_sublabel_below field_description_below gfield_visibility_visible' ><h2 class='gsection_title'>Vehicle Info</h2></li><li id='field_7_35' class='gfield gfield_html gfield_html_formatted gfield_no_follows_desc field_sublabel_below field_description_below gfield_visibility_visible' ></ul><ul class="formsection"></li><li id='field_7_49' class='gfield dv-form-textbox dv-form-name gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label gfield_label_before_complex' >Name<span class='gfield_required'>*</span></label><div class='ginput_complex ginput_container no_prefix has_first_name no_middle_name has_last_name no_suffix gf_name_has_2 ginput_container_name' id='input_7_49'> 3219
3220 <span id='input_7_49_3_container' class='name_first' > 3221 <input type='text' name='input_49.3' id='input_7_49_3' value='' aria-label='First name' tabindex='50' aria-required="true" aria-invalid="false" placeholder='First'/> 3222 <label for='input_7_49_3' >First</label> 3223 </span> 3224 3225 <span id='input_7_49_6_container' class='name_last' > 3226 <input type='text' name='input_49.6' id='input_7_49_6' value='' aria-label='Last name' tabindex='52' aria-required="true" aria-invalid="false" placeholder='Last'/> 3227 <label for='input_7_49_6' >Last</label> 3228 </span> 3229 3230 </div></li><li id='field_7_3' class='gfield dv-form-textbox field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_3' >Phone</label><div class='ginput_container ginput_container_phone'><input name='input_3' id='input_7_3' type='text' value='' class='medium' tabindex='54' aria-invalid="false" /></div></li><li id='field_7_4' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_4' >Email<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_email'> 3231 <input name='input_4' id='input_7_4' type='text' value='' class='medium' tabindex='55' aria-required="true" aria-invalid="false"/> 3232 </div></li><li id='field_7_5' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' >Contact Preference?<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_radio'><ul class='gfield_radio' id='input_7_5'><li class='gchoice_7_5_0'><input name='input_5' type='radio' value='Phone' id='choice_7_5_0' tabindex='56' /><label for='choice_7_5_0' id='label_7_5_0'>Phone</label></li><li class='gchoice_7_5_1'><input name='input_5' type='radio' value='Email' id='choice_7_5_1' tabindex='57' /><label for='choice_7_5_1' id='label_7_5_1'>Email</label></li></ul></div></li><li id='field_7_36' class='gfield gfield_html gfield_html_formatted gfield_no_follows_desc field_sublabel_below field_description_below gfield_visibility_visible' ></ul><ul></li><li id='field_7_7' class='gfield gsection field_sublabel_below field_description_below gfield_visibility_visible' ><h2 class='gsection_title'>What Are You Looking For?</h2></li><li id='field_7_37' class='gfield gfield_html gfield_html_formatted gfield_no_follows_desc field_sublabel_below field_description_below gfield_visibility_visible' ></ul><ul class="formsection"></li><li id='field_7_41' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' >Type<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_radio'><ul class='gfield_radio' id='input_7_41'><li class='gchoice_7_41_0'><input name='input_41' type='radio' value='New' id='choice_7_41_0' tabindex='58' /><label for='choice_7_41_0' id='label_7_41_0'>New</label></li><li class='gchoice_7_41_1'><input name='input_41' type='radio' value='Used' id='choice_7_41_1' tabindex='59' /><label for='choice_7_41_1' id='label_7_41_1'>Used</label></li><li class='gchoice_7_41_2'><input name='input_41' type='radio' value='Any' id='choice_7_41_2' tabindex='60' /><label for='choice_7_41_2' id='label_7_41_2'>Any</label></li></ul></div></li><li id='field_7_50' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_50' >Year<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_text'><input name='input_50' id='input_7_50' type='text' value='' class='medium' tabindex='61' placeholder='XXXX' aria-required="true" aria-invalid="false" /></div></li><li id='field_7_44' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_44' >Mileage (Max)<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_select'><select name='input_44' id='input_7_44' class='medium gfield_select' tabindex='62' aria-required="true" aria-invalid="false"><option value='5000' >5000</option><option value='10000' >10000</option><option value='15000' >15000</option><option value='20000' >20000</option><option value='25000' >25000</option><option value='30000' >30000</option><option value='40000' >40000</option><option value='50000' >50000</option><option value='60000' >60000</option><option value='70000' >70000</option><option value='80000' >80000</option><option value='90000' >90000</option><option value='100000' >100000</option><option value='150000' >150000</option><option value='Any' >Any</option></select></div></li><li id='field_7_45' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_45' >Price (Max)<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_select'><select name='input_45' id='input_7_45' class='medium gfield_select' tabindex='63' aria-required="true" aria-invalid="false"><option value='Any' >Any</option><option value='$200000' >$200000</option><option value='$150000' >$150000</option><option value='$120000' >$120000</option><option value='$100000' >$100000</option><option value='$90000' >$90000</option><option value='$80000' >$80000</option><option value='$70000' >$70000</option><option value='$60000' >$60000</option><option value='$50000' >$50000</option><option value='$40000' >$40000</option><option value='$30000' >$30000</option><option value='$25000' >$25000</option><option value='$20000' >$20000</option><option value='$15000' >$15000</option><option value='$10000' >$10000</option><option value='$5000' >$5000</option></select></div></li><li id='field_7_9' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_9' >Make<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_text'><input name='input_9' id='input_7_9' type='text' value='' class='medium' tabindex='64' aria-required="true" aria-invalid="false" /></div></li><li id='field_7_10' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_10' >
3232Model<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_text'><input name='input_10' id='input_7_10' type='text' value='' class='medium' tabindex='65' aria-required="true" aria-invalid="false" /></div></li><li id='field_7_11' class='gfield dv-form-textbox field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_11' >Trim</label><div class='ginput_container ginput_container_text'><input name='input_11' id='input_7_11' type='text' value='' class='medium' tabindex='66' aria-invalid="false" /></div></li><li id='field_7_46' class='gfield dv-form-textbox field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_46' >Color</label><div class='ginput_container ginput_container_text'><input name='input_46' id='input_7_46' type='text' value='' class='medium' tabindex='67' aria-invalid="false" /></div></li><li id='field_7_12' class='gfield dv-form-textbox gfield_contains_required field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' >Transmission<span class='gfield_required'>*</span></label><div class='ginput_container ginput_container_radio'><ul class='gfield_radio' id='input_7_12'><li class='gchoice_7_12_0'><input name='input_12' type='radio' value='Automatic' id='choice_7_12_0' tabindex='68' /><label for='choice_7_12_0' id='label_7_12_0'>Automatic</label></li><li class='gchoice_7_12_1'><input name='input_12' type='radio' value='Manual' id='choice_7_12_1' tabindex='69' /><label for='choice_7_12_1' id='label_7_12_1'>Manual</label></li></ul></div></li><li id='field_7_47' class='gfield dv-form-textbox field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_47' >Message</label><div class='ginput_container ginput_container_textarea'><textarea name='input_47' id='input_7_47' class='textarea small' tabindex='70' aria-invalid="false" rows='10' cols='50'></textarea></div></li><li id='field_7_38' class='gfield gfield_html gfield_html_formatted gfield_no_follows_desc field_sublabel_below field_description_below gfield_visibility_visible' ></ul><ul></li><li id='field_7_39' class='gfield gfield_html gfield_html_formatted gfield_no_follows_desc field_sublabel_below field_description_below gfield_visibility_visible' ><div class="bottomsection">By submitting this form, you agree to be contacted with information regarding the vehicle you are searching for.</div></ul></li><li id='field_7_40' class='gfield hidden field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_40' >Referral ID</label></li><li id='field_7_51' class='gfield gform_validation_container field_sublabel_below field_description_below gfield_visibility_visible' ><label class='gfield_label' for='input_7_51' >Comments</label><div class='ginput_container'><input name='input_51' id='input_7_51' type='text' value='' /></div><div class='gfield_description' id='gfield_description__51'>This field is for validation purposes and should be left unchanged.</div></li> 3233 </ul></div> 3234 <div class='gform_footer left_label'> <input type='submit' id='gform_submit_button_7' class='gform_button button' value='Let us find it!' tabindex='71' onclick='if(window["gf_submitting_7"]){return false;} window["gf_submitting_7"]=true; ' onkeypress='if( event.keyCode == 13 ){ if(window["gf_submitting_7"]){return false;} window["gf_submitting_7"]=true; jQuery("#gform_7").trigger("submit",[true]); }' /> 3235 <input type='hidden' class='gform_hidden' name='is_submit_7' value='1' /> 3236 <input type='hidden' class='gform_hidden' name='gform_submit' value='7' /> 3237 3238 <input type='hidden' class='gform_hidden' name='gform_unique_id' value='' /> 3239 <input type='hidden' class='gform_hidden' name='state_7' value='WyJbXSIsIjExNzhmZjIwMGMwYzVkM2UzYjE0NGUyMzc1MWQyNTczIl0=' /> 3240 <input type='hidden' class='gform_hidden' name='gform_target_page_number_7' id='gform_target_page_number_7' value='0' /> 3241 <input type='hidden' class='gform_hidden' name='gform_source_page_number_7' id='gform_source_page_number_7' value='1' /> 3242 <input type='hidden' name='gform_field_values' value='' /> 3243 3244 </div> 3245 <p class="gf-consent-text" style="margin-top: 12px; font-size:11px; color:#999B9F; line-height:1.1rem;">By submitting your information, you consent to receive communications from , including SMS, voice calls, and/or emails, regarding our products, services, and promotional offers. These communications may be sent using automated technology. Consent is not a condition of purchase. Standard messaging and data rates may apply.</p><div class="dealer-disclaimer-container-class"></div><p style="display: none !important;"><label>Δ<textarea name="ak_hp_textarea" cols="45" rows="8" maxlength="100"></textarea></label><input type="hidden" id="ak_js_1" name="ak_js" value="224"/>
3245<script>document.getElementById( "ak_js_1" ).setAttribute( "value", ( new Date() ).getTime() );</script>
3245</p></form> 3246 </div></div></div> 3247 3248 3249 <style> 3250 .listing .vehicle-views .srp-views { 3251 top: 10px; 3252 right: 10px; 3253 } 3254 </style>
3254<script> 3255 function toggleMobileButton() { 3256 3257 var isMobile = window.innerWidth <= 768; 3258 var button = document.querySelector('.srp-cta-6-btn'); 3259 3260 if (!isMobile && button) { 3261 button.parentNode.removeChild(button); 3262 } 3263} 3264toggleMobileButton(); 3265window.onload = toggleMobileButton; 3266window.onresize = toggleMobileButton; 3267</script>
3267 3268 3269
3270<script> 3271 /** 3272 * The loading overlay needs a deadline as well as a success condition. 3273 * 3274 * This poll had no upper bound: if results never arrived - slow connection, 3275 * Algolia error, an exception thrown earlier on the page - it retried every 3276 * 100ms indefinitely and the overlay stayed up forever. Measured on prod 3277 * throttled to Slow 3G, results had still not rendered 90 seconds in and this 3278 * was still looping. 3279 * 3280 * It went unnoticed for so long only because .srpLoading was silently unstyled: 3281 * a Stylus indentation bug folded its declarations into a selector list, so 3282 * browsers dropped the entire rule and the overlay covered nothing. See the 3283 * note in media/css/srpCSS/algolia.styl. Now that the rule compiles, this is a 3284 * genuinely opaque full-viewport layer at z-index 999, and an unbounded wait 3285 * means a shopper stuck on a grey screen with no way past it. 3286 * 3287 * Revealing a half-built page is the better failure. The above-the-fold 3288 * controls are styled from algolia.css at first paint, so what shows through is 3289 * presentable even mid-load. 3290 * 3291 * Measured from performance.now() - milliseconds since navigation start - and 3292 * NOT from a Date.now() captured when this script runs. This block sits around 3293 * line 3,260 of an 8,800-line document, so on a slow connection it executes 3294 * many seconds after the overlay first paints; anchoring the deadline to script 3295 * execution would silently stretch it by however long the HTML took to get 3296 * here. The budget is a fixed span of page life, not that span measured from 3297 * whenever-this-parsed. 3298 * 3299 * Configurable at Theme Options -> Performance -> "Maximum time to show the 3300 * loading overlay". There is deliberately no switch to turn the deadline off: 3301 * unbounded is the bug it replaced. 3302 */ 3303 var SRP_LOADING_MAX_MS = 12000; 3304 3305 function checkForResults() { 3306 if ($("#srp-results .ais-Hits-item")[0] || $("#srp-results .srp-no-results").is(":visible")) { 3307 $(".srpLoading").remove(); 3308 } else if (performance.now() > SRP_LOADING_MAX_MS) { 3309 $(".srpLoading").remove(); 3310 } else { 3311 setTimeout(checkForResults, 100); 3312 } 3313 } 3314 3315 3316 checkForResults(); 3317 //Moroney Label Click Event - SRP 3318 function callWindowSticker(vin,year,make,model,condition) { 3319 if (String(make).toLowerCase() === 'kia' && String(condition).toLowerCase() === 'new') { 3320 if (window.AutoGoKiaWindowSticker) { 3321 window.AutoGoKiaWindowSticker.open(`/wp-json/dealer/v1/kia-window-sticker/${encodeURIComponent(vin)}`); 3322 } 3323 return false; 3324 } 3325 3326 let windowSticker = `https://api.toyotainventory.com/vehicles/${vin}/monroney`; 3327 3328 //SDIS Auth Token for Window Stickers 3329 $.ajax({ 3330 url: windowSticker, 3331 type: 'GET', 3332 beforeSend: function (xhr) { 3333 xhr.setRequestHeader('Authorization', 'Bearer RABWAGUAbgBvAG0AVABvAHkAbwB0AGEAMgAwADIAMgA='); 3334 }, 3335 }); 3336 3337 sd('dataLayer', { 3338 linkType: 'Monroney Label', 3339 vehicleDetails: { 3340 status: 'new', 3341 year: year, 3342 make: make, 3343 model: model, 3344 vin: vin, 3345 }, 3346 events: 'linkClick' 3347 }); 3348 sd('send'); 3349 } 3350</script>
3350 3351 3352
3353<script> 3354 /** 3355 * Begin Quick Form Event Listener Logic 3356 */ 3357 var $isVDP = jQuery("#fixed-info-container"); 3358 3359 function populateHiddenFields(formInstance) { 3360 if (typeof DVHydrate !== 'undefined') { 3361 DVHydrate.populateFormFields("#" + formInstance); 3362 } 3363 } 3364 3365 function getQuickFormCookies() { 3366 var cookies = {}; 3367 document.cookie.split(";").forEach(cookie => { 3368 var parts = cookie.trim().split("="); 3369 var name = parts[0]; 3370 var value = parts[1]; 3371 if (name.startsWith("quickFormUnlocked_")) { 3372 cookies[name] = value; 3373 } 3374 }); 3375 return cookies; 3376 } 3377 3378 function checkAndHideForms() { 3379 var cookies = getQuickFormCookies(); 3380 3381 if (Object.keys(cookies).length === 0) return; 3382 3383 3384 var $vdpContainer = jQuery("#fixed-info-container"); 3385 var isVDP = $vdpContainer.length > 0; 3386 3387 // Get the condition from the container 3388 var condition = isVDP ? 3389 $vdpContainer.data("vehicle-condition").toLowerCase() : 3390 jQuery(".listing").first().data("vehicle-condition").toLowerCase(); 3391
3392 // Check for condition-specific "all" cookie 3393 if (`quickFormUnlocked_all_${condition}` in cookies) { 3394 jQuery(".da-quick-form").remove(); 3395 jQuery(".da-quick-form-unlocked").show(); 3396 jQuery("#da-quick-form-unlocked").show(); 3397 jQuery("#vdp-pricingheader-container").remove(); 3398 return; 3399 } 3400 3401 if ($vdpContainer.length > 0) { 3402 // VDP logic 3403 var vin = $vdpContainer.data("vehicle-vin"); 3404 if (vin && "quickFormUnlocked_" + vin in cookies) { 3405 jQuery(".da-quick-form").remove(); 3406 } 3407 } else { 3408 // SRP logic 3409 jQuery(".da-quick-form").each(function() { 3410 var $form = jQuery(this); 3411 var $parentCard = $form.closest(".listing"); 3412 var vin = $parentCard.data("vehicleVin"); 3413 3414 if (vin && "quickFormUnlocked_" + vin in cookies) { 3415 $form.remove(); 3416 } 3417 }); 3418 } 3419 } 3420 3421 if($isVDP.length > 0) { 3422 checkAndHideForms(); 3423 } 3424 3425 const handleInventoryLoad = (event) => { 3426 jQuery(".da-quick-form").each(function() { 3427 var formId = jQuery(this).attr("id"); 3428 populateHiddenFields(formId); 3429 }); 3430 }; 3431 3432 window.addEventListener("Inventory:loaded_srp", () => { 3433 handleInventoryLoad(); 3434 checkAndHideForms(); 3435 3436 jQuery("#srp-filters, #pagination-top, #pagination-bottom, #filterTags, #srp-filters-reset-btn, #dv-srp-clear-filters, #clearSearchResults, #showFiltersNonLegacy, .ais-Pagination-link, .ais-Pagination").click(function(){ 3437 checkAndHideForms(); 3438 }); 3439 }); 3440 3441 window.addEventListener("Inventory:loaded_vdp", handleInventoryLoad); 3442 3443 /** 3444 * e/o: Begin Quick Form Event Listener Logic 3445 */ 3446</script>
3446 3447 3448<!-- Pinned to the exact version @2 resolves to today. The stale-search 3449 canceller below assumes this version's axios/XHR transport; a CDN-resolved 3450 minor that swapped in the fetch adapter would silently disable it. The 3451 pin is also what makes integrity possible - a floating @2 changes bytes 3452 by design, so it could never carry one. Hash is sha384 of the 145,726-byte 3453 2.9.0 dist, same treatment as the instantsearch tag below. -->
3454<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/typesense-instantsearch-adapter.min.js" integrity="sha384-B47IWeyyh8xnZkeL6rPg51tYX2fWwgI6CbkJN8BYp3VKHngE3hM/2Bqn8JTE8c92" crossorigin="anonymous"></script>
vendor: 1 bytes, line 3454
3454
3455<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/instantsearch.production.min.js" integrity="sha256-r9HX5YzBrppuVpgfMA3USvgS2jEdIBPJ3ntsidyTNl8=" crossorigin="anonymous"></script>
vendor: 1 bytes, line 3455
3455
3456<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/jquery.formatCurrency-1.4.0.min.js?v=1.598.636"></script>
vendor: 1 bytes, line 3456
3456
3457<script defer src="https://www.youtube.com/iframe_api"></script>
vendor: 1 bytes, line 3457
3457
3458<script> 3459 var srpCondition = "New"; 3460 var indexName = "vehicles-TOY32136"; 3461 var cityState = "Wilson, NC"; 3462 var isNexusToyota = "1"; 3463 var isNexusHonda = ""; 3464 var isNexusAcura = ""; 3465 var isNexusEnabled = "1"; 3466 var dealerRegion = "SET10"; 3467 var distanceUnit = "Mile"; 3468 var haveSdAnalytics = false; 3469 haveSdAnalytics = true; var searchChangedTimer = null; 3470 var lastSdSearchStateSignature = null; 3471 var lastSdFacetStateSignature = null; 3472 var sdInitialFilterSearchSent = false; 3473 var sdFormShownPending = false; 3474 3475 /** 3476 * "formInitiation already sent for the currently shown form". 3477 * 3478 * Module scope on purpose. This was a `var formInitHandled = false` declared 3479 * inside the no-results branch, immediately before binding the click handler - 3480 * so every run of that branch bound another handler, and each one closed over 3481 * its own copy of the flag. After N no-result renders a single click ran N 3482 * handlers, every one of them believing it was the first, and sent N 3483 * formInitiation events. That was duplicated analytics, not just wasted work. 3484 * 3485 * Still reset where the original was, so the semantics are unchanged: one 3486 * initiation per form shown. 3487 */ 3488 var sdFormInitHandled = false; 3489 3490 /** 3491 * A query-only search owes Shift Digital a pageview and filterSearch on top 3492 * of typedSearch, and typedSearch has to land first. 3493 * 3494 * The render for a keystroke arrives long before the 800ms typedSearch 3495 * debounce, so the render only marks the send as pending and the debounce 3496 * flushes it. The timer is the fallback for query changes with no typing 3497 * behind them - the clear-search and reset buttons call setQuery('') - which 3498 * would otherwise leave the flag pending forever. 3499 */ 3500 var lastSdQuery = null; 3501 var sdQueryAnalyticsPending = false; 3502 var sdQueryAnalyticsTimer = null; 3503 var currentRefinements = {}; 3504 var vehiclesList = []; 3505 let userInteractedWithFacets = false; 3506 var srpDealerId = "TOY32136"; 3507 var dealerGroupSite = "GRP"; 3508 3509 const showConditionalIncentives = ""; 3510 3511 //Homepage/Menu Link Model Map for correct facetting 3512 const modelFormatMap = { 3513 'bz4x': 'bZ4X', 3514 'rav4': 'RAV4', 3515 '4runner': '4Runner', 3516 'i-force': 'Tundra i-FORCE MAX', 3517 'tundra i-force max': 'Tundra i-FORCE MAX', 3518 'hr-v': 'HR-V', 3519 'cr-v': 'CR-V', 3520 'hr-v hybrid': 'HR-V Hybrid', 3521 'cr-v hybrid': 'CR-V Hybrid', 3522 'gr86': 'GR86', 3523 'rav4 prime': 'RAV4 Prime', 3524 'rav4 hybrid': 'RAV4 Hybrid', 3525 'titan xd': 'Titan XD', 3526 'gt-r': 'GT-R', 3527 'leaf': 'LEAF', 3528 'es': 'ES', 3529 'is': 'IS', 3530 'is 500': 'IS 500', 3531 'ls': 'LS', 3532 'es hybrid': 'ES Hybrid', 3533 'lc hybrid': 'LC Hybrid', 3534 'ls hybrid': 'LS Hybrid', 3535 'nx hybrid': 'NX Hybrid', 3536 'nx phev': 'NX PHEV', 3537 'rx phev': 'RX PHEV', 3538 'rx hybrid': 'RX Hybrid', 3539 'ux hybrid': 'UX Hybrid', 3540 'gx': 'GX', 3541 'lx': 'LX', 3542 'nx': 'NX', 3543 'rx': 'RX', 3544 'ux': 'UX', 3545 'lc convertible': 'LC Convertible', 3546 'rc': 'RC', 3547 'rc f': 'RC F', 3548 'lc': 'LC', 3549 'rz': 'RZ', 3550 'tx': 'TX', 3551 'tx phev': 'TX PHEV', 3552 'tx 500h': 'TX 500h', 3553 'ux phev': 'UX PHEV', 3554 'i4': 'i4', 3555 'i5': 'i5', 3556 'i7': 'i7', 3557 'ix': 'iX', 3558 'adx': 'ADX', 3559 'mdx': 'MDX', 3560 'rdx': 'RDX', 3561 'tlx': 'TLX', 3562 'zdx': 'ZDX', 3563 'sierra ev': 'Sierra EV', 3564 'sierra hd': 'Sierra HD', 3565 'hummer ev pickup': 'Hummer EV Pickup', 3566 'hummer ev suv': 'Hummer EV SUV', 3567 'yukon xl': 'Yukon XL', 3568 'outlander phev': 'Outlander PHEV', 3569 'gla': 'GLA', 3570 'glb': 'GLB', 3571 'glc': 'GLC', 3572 'gle': 'GLE', 3573 'gls': 'GLS', 3574 'glc coupe': 'GLC Coupe', 3575 'gle coupe': 'GLE Coupe', 3576 'gls coupe': 'GLS Coupe', 3577 'g-class': 'G-Class', 3578 'c-class': 'C-Class', 3579 'c-class sedan': 'C-Class Sedan', 3580 'e-class': 'E-Class', 3581 'e-class sedan': 'E-Class Sedan', 3582 's-class': 'S-Class', 3583 's-class sedan': 'S-Class Sedan', 3584 'eqb': 'EQB', 3585 'eqc': 'EQC', 3586 'eqe': 'EQE', 3587 'eqs': 'EQS', 3588 'eqs suv': 'EQS SUV', 3589 'cla': 'CLA', 3590 'c-class cabriolet': 'C-Class Cabriolet', 3591 'amg®': 'AMG®', 3592 'amg® gt': 'AMG® GT', 3593 }; 3594 3595 function formatModelName(model) { 3596 const lowerCaseModel = model.toLowerCase(); 3597 if (modelFormatMap[lowerCaseModel]) { 3598 return modelFormatMap[lowerCaseModel]; 3599 } else { 3600 const words = model.split(' '); 3601 return words.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(' '); 3602 } 3603 } 3604
3605 /** 3606 * Build the page title from the current selected refinements 3607 */ 3608 function buildTitle(refinementList) 3609 { 3610 let titleString = ""; 3611 let modelString = ""; 3612 let bodyString = ""; 3613 let condition = srpCondition; 3614 let vehicleHistoryString = ""; 3615 3616 currentRefinements = refinementList; 3617 3618 if(refinementList.body && condition == 'New'){ 3619 if(refinementList.body.length == 1){ 3620 titleString = "Toyota" + " " + refinementList.body[0] + " Models"; 3621 } else{ 3622 for( var bod in refinementList.body) 3623 { 3624 bodyString += " " + refinementList.body[bod] + ","; 3625 titleString = "Toyota" + " " + bodyString + " Models"; 3626 } 3627 } 3628 return titleString; 3629 } 3630 3631 if(refinementList.body && condition == 'Used'){ 3632 if(refinementList.body.length == 1){ 3633 titleString = refinementList.body[0] + " Models"; 3634 } else{ 3635 for( var bod in refinementList.body) 3636 { 3637 bodyString += " " + refinementList.body[bod] + ","; 3638 titleString = bodyString + " Models"; 3639 } 3640 } 3641 return titleString; 3642 } 3643 3644 if (refinementList.make && refinementList.make.length == 1) 3645 { 3646 3647 if(refinementList.body && condition == 'Used'){ 3648 if(refinementList.body.length == 1){ 3649 titleString = refinementList.make + " " + refinementList.body[0] + " Models"; 3650 } else{ 3651 for( var bod in refinementList.body) 3652 { 3653 bodyString += " " + refinementList.body[bod] + ","; 3654 } 3655 for( var make in refinementList.make) 3656 { 3657 makeString += " " + refinementList.make[make] + ","; 3658 3659 } 3660 titleString = makeString + " " + bodyString + " Models"; 3661 3662 } 3663 return titleString; 3664 } 3665 3666 if (refinementList.model && refinementList.model.length == 1) 3667 { 3668 titleString = refinementList.make[0] + " " + refinementList.model[0] + " Vehicles"; 3669 3670 return titleString; 3671 } 3672 else if (refinementList.model) 3673 { 3674 for (var model in refinementList.model) 3675 { 3676 titleString += " " + refinementList.model[model] + ","; 3677 } 3678 3679 return titleString; 3680 } 3681 else 3682 { 3683 titleString = refinementList.make[0] + " Models"; 3684 return titleString; 3685 } 3686 } 3687 else if (refinementList.make) 3688 { 3689 if (refinementList.model) 3690 { 3691 if (refinementList.model.length == 1) 3692 { 3693 titleString += " " + refinementList.model[0]; 3694 } 3695 else 3696 { 3697 for (var model in refinementList.model) 3698 { 3699 titleString += " " + refinementList.model[model] + ","; 3700 } 3701 } 3702 3703 titleString += " Models"; 3704 3705 return titleString; 3706 } 3707 for (var make in refinementList.make) 3708 { 3709 titleString += " " + refinementList.make[make] + ","; 3710 } 3711 3712 titleString += " Models"; 3713 3714 return titleString; 3715 } 3716 else{ 3717 if(refinementList.model){ 3718 3719 if (refinementList.model.length == 1) 3720 { 3721 modelString += " " + refinementList.model[0]; 3722 } 3723 else 3724 { 3725 for (var model in refinementList.model) 3726 { 3727 modelString += " " + refinementList.model[model] + ","; 3728 } 3729 } 3730 if(condition == 'Used'){ 3731 titleString += " " + modelString + " Models"; 3732 } else{ 3733 titleString += "Toyota" + " " + modelString + " Models"; 3734 } 3735 return titleString; 3736 } 3737 } 3738 3739 //Build Title for Vehicle History 3740 if(refinementList.vehicleHistory && condition == "Used") 3741 { 3742 if(refinementList.vehicleHistory.length == 1) 3743 { 3744 titleString = refinementList.vehicleHistory[0] + " Models"; 3745 } 3746 else 3747 { 3748 for (var bod in refinementList.vehicleHistory) 3749 { 3750 vehicleHistoryString += " " + refinementList.vehicleHistory[bod] + ","; 3751 } 3752 titleString = vehicleHistoryString + " Models"; 3753 } 3754 return titleString; 3755 } 3756 3757 //Build title for flags.type 3758 if (refinementList["flags.type"] && refinementList["flags.type"].length > 0) { 3759 let flagsTypeString = ""; 3760 3761 if (refinementList["flags.type"].length === 1) { 3762 titleString = refinementList["flags.type"][0] + " Models"; 3763 } else { 3764 for (let i = 0; i < refinementList["flags.type"].length; i++) { 3765 flagsTypeString += refinementList["flags.type"][i] + ", "; 3766 } 3767 flagsTypeString = flagsTypeString.slice(0, -2); 3768 titleString = flagsTypeString + " Models"; 3769 } 3770 3771 return titleString; 3772 } 3773 3774 3775 return "Toyota Vehicles"; 3776 } 3777
3778 //Build meta description for SRP filters 3779 function buildDescription(refinementList){ 3780 3781 modelString = ""; 3782 makeString = ""; 3783 featureString = ""; 3784 fuelString = ""; 3785 colorString = ""; 3786 bodyString = ""; 3787 trimString = ""; 3788 3789 currentRefinements = refinementList 3790 3791 if(refinementList.body && refinementList.features){ 3792 if(refinementList.body.length == 1 && refinementList.features.length == 1){ 3793 bodyString += "" + refinementList.body[0] + "s"; 3794 featureString +="" + refinementList.features[0] + " "; 3795 } else{ 3796 for( var bod in refinementList.body) 3797 { 3798 bodyString += " " + refinementList.body[bod] + "s,"; 3799 } 3800 3801 for( var feat in refinementList.features) 3802 { 3803 featureString += " " + refinementList.features[feat] + ", "; 3804 } 3805 } 3806 3807 let newDesc = `Shop ${srpCondition} ${bodyString} with ${featureString}in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3808 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3809 3810 } 3811 3812 if(refinementList.model){ 3813 3814 if(srpCondition == "New"){ 3815 3816 if( refinementList.model.length >= 1 ){ 3817 3818 if (refinementList.model.length == 1) 3819 { 3820 modelString += " " + refinementList.model[0]; 3821 } 3822 else 3823 { 3824 for (var model in refinementList.model) 3825 { 3826 modelString += " " + refinementList.model[model] + ","; 3827 } 3828 3829 } 3830 3831 if(refinementList.features){ 3832 if(refinementList.features.length == 1){ 3833 featureString += "" + refinementList.features[0]; 3834 } else{ 3835 for( var feat in refinementList.features) 3836 { 3837 featureString += " " + refinementList.features[feat] + ","; 3838 } 3839 } 3840 3841 let newDesc = `Shop ${srpCondition} Toyota ${modelString} vehicles with ${featureString} in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3842 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3843 } 3844 3845 if(refinementList.fuel){ 3846 fuelString += " " + refinementList.fuel[0]; 3847 let newDesc = `Shop ${srpCondition} Toyota ${modelString} ${fuelString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3848 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3849 } 3850 3851 if(refinementList.generic_color){ 3852 if(refinementList.generic_color.length == 1){ 3853 colorString += " " + refinementList.generic_color[0] + " "; 3854 }else{ 3855 for( var color in refinementList.generic_color) 3856 { 3857 colorString += " " + refinementList.generic_color[color] + ","; 3858 } 3859 } 3860 3861 let newDesc = `Shop ${srpCondition} ${colorString} Toyota ${modelString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3862 3863 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc) 3864 } 3865 3866 if(refinementList.trim){ 3867 if(refinementList.trim.length == 1){ 3868 trimString += "" + refinementList.trim[0]; 3869 } else{ 3870 for( var feat in refinementList.trim) 3871 { 3872 trimString += " " + refinementList.trim[feat] + ","; 3873 } 3874 } 3875 3876 let newDesc = `Shop ${srpCondition}
3876 ${modelString} in ${trimString} trim levels in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3877 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3878 } 3879 3880 let newDesc = `Shop ${srpCondition} Toyota ${modelString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}`; 3881 3882 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc) 3883 3884 } 3885 } 3886 } 3887 if (refinementList.make){ 3888 3889 3890 if(refinementList.make.length == 1){ 3891 makeString += " " + refinementList.make[0]; 3892 3893 } 3894 else 3895 { 3896 3897 for (var make in refinementList.make) 3898 { 3899 makeString += " " + refinementList.make[make] + ","; 3900 } 3901 } 3902 3903 if(refinementList.features){ 3904 if(refinementList.features.length == 1){ 3905 featureString += " " + refinementList.features[0]; 3906 } else{ 3907 for( var feat in refinementList.features) 3908 { 3909 featureString += " " + refinementList.features[feat] + ","; 3910 } 3911 } 3912 3913 let newDesc = `Shop ${srpCondition} ${makeString} vehicles with${featureString} in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3914 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3915 } 3916 3917 if(refinementList.fuel){ 3918 fuelString += " " + refinementList.fuel[0]; 3919 let newDesc = `Shop ${srpCondition} ${makeString} ${fuelString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3920 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3921 } 3922 3923 if(refinementList.generic_color){ 3924 if(refinementList.generic_color.length == 1){ 3925 colorString += " " + refinementList.generic_color[0] + " "; 3926 }else{ 3927 for( var color in refinementList.generic_color) 3928 { 3929 colorString += " " + refinementList.generic_color[color] + ","; 3930 } 3931 } 3932 3933 let newDesc = `Shop ${srpCondition} ${colorString} ${makeString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3934 3935 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc) 3936 } 3937 3938 3939 if(refinementList.body){ 3940 if(refinementList.body.length == 1){ 3941 bodyString += "" + refinementList.body[0] + "s"; 3942 } else{ 3943 for( var feat in refinementList.body) 3944 { 3945 bodyString += " " + refinementList.body[feat] + "s,"; 3946 } 3947 } 3948 3949 let newDesc = `Shop ${srpCondition} ${makeString} ${bodyString} in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3950 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3951 } 3952 3953 3954 let newDesc = `Shop ${srpCondition} ${makeString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3955 3956 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc) 3957 3958 3959 } 3960 3961 if(refinementList.genericColor){ 3962 if(refinementList.genericColor.length == 1){ 3963 colorString += " " + refinementList.genericColor[0] + " "; 3964 }else{ 3965 for( var color in refinementList.genericColor) 3966 { 3967 colorString += " " + refinementList.genericColor[color] + ","; 3968 } 3969 } 3970 3971 let newDesc = `Shop ${srpCondition} ${colorString} Toyota vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}`; 3972 3973 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc) 3974 } 3975 3976 if(refinementList.fuel){ 3977 fuelString += " " + refinementList.fuel[0]; 3978 let newDesc = `Shop ${srpCondition} Toyota ${fuelString} vehicles in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3979 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3980 } 3981 3982 if(refinementList.features){ 3983 if(refinementList.features.length == 1){ 3984 featureString += "" + refinementList.features[0]; 3985 } else{ 3986 for( var feat in refinementList.features) 3987 { 3988 featureString += " " + refinementList.features[feat] + ","; 3989 } 3990 } 3991 3992 let newDesc = `Shop ${srpCondition}
3992 Toyota ${modelString} vehicles with ${featureString} in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 3993 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 3994 } 3995 3996 if(refinementList.body){ 3997 if(refinementList.body.length == 1){ 3998 bodyString += "" + refinementList.body[0] + "s"; 3999 } else{ 4000 for( var feat in refinementList.body) 4001 { 4002 bodyString += " " + refinementList.body[feat] + "s,"; 4003 } 4004 } 4005 4006 let newDesc = `Shop ${srpCondition} ${bodyString} in Stock and Online today at , ${srpCondition} Toyota dealership in ${cityState}` 4007 return document.querySelector('meta[name="description"]').setAttribute("content", newDesc); 4008 } 4009 4010 return 4011 4012 } 4013 4014 /** 4015 * Trigger Inventory Loaded Event 4016 */ 4017 function _triggerInventoryLoaded() { 4018 const event = new Event('Inventory:loaded_srp'); 4019 window.dispatchEvent(event); 4020 } 4021 4022 /** 4023 * Search for Smart Path Disclaimer Function 4024 * @author layth abdelqader 4025 * @param {string} text - text to filter by 4026 * @param {string} cname - class name of element 4027 */ 4028 function SmartPathDisclaimer(text, cname) { 4029 // set up replacement fn 4030 var doReplacement = function(interval) { 4031 // clear interval 4032 clearInterval(interval); 4033 // lets start the loop and find all classnames/text that match 4034 const container = [...document.querySelectorAll(cname)]; 4035 for (let i = 0; i < container.length; i++) { 4036 var classListing = [...container[i].classList]; 4037 if (container[i].textContent.includes(text) && container[i].textContent.includes("transit")) 4038 { 4039 if(!container[i].textContent.includes(text + ':')){ 4040 container[i].innerHTML = container[i].innerHTML.replace(text, "<strong>
4040" + text + ':' + "</strong>"); 4041 } 4042 } else if (container[i].textContent.includes(text) && container[i].textContent.includes("build phase")) { 4043 if(!container[i].textContent.includes(text + ':')){ 4044 container[i].innerHTML = container[i].innerHTML.replace(text, "<strong>" + text + ':' + "</strong>"); 4045 } 4046 } else if (container[i].textContent.includes(text)) { 4047 container[i].innerHTML = container[i].innerHTML.replace(text, "<strong>" + text + "</strong>"); 4048 } else { 4049 container[i].classList.remove( 4050 "dv-sp-disclaimer-strong" 4051 ); 4052 } 4053 } 4054 }; 4055 // set up interval and wait for dgdatahub to load 4056 var interval = setInterval(function () { 4057 if (window.DGDataHub != undefined) { 4058 if (typeof window.DGDataHub.getWarningState !== "undefined" && window.DGDataHub.getWarningState().dgLoaded) { 4059 doReplacement(interval) 4060 } 4061 } 4062 }, 200); 4063 } 4064 4065 /** 4066 * Search highlighting is computed, transferred and parsed, then thrown away. 4067 * 4068 * The adapter defaults highlight_full_fields to the whole query_by list, so 4069 * every response carries per-hit highlight blocks for all sixteen fields. 4070 * Nothing reads them: no template in this file touches _highlightResult, 4071 * and never has. Both highlight knobs are set to "none" below: the adapter 4072 * injects highlight_full_fields on its own, which of the two wins is 4073 * decided server-side, and naming both removes the doubt for free. 4074 * 4075 * Sized honestly before assuming it mattered: on the live i95 collection 4076 * the highlight blocks are about 1% of a 428KB keystroke response, because 4077 * the weight is the documents themselves - imageUrls is 48% of a 25KB hit 4078 * and conditionalIncentives another 32%, and both are genuinely rendered, 4079 * so neither can be excluded. This trim is kept because it is free and 4080 * strictly correct - the server skips work nobody consumes - not because 4081 * it moves the needle. Anyone tempted to chase response size further: 4082 * measure the per-field split first, and note that the transfer was never 4083 * what blocked the main thread - the re-render is. 4084 * 4085 * Gated on Theme Options -> Performance -> "Skip unused search highlighting" 4086 * because a dealer's custom runtime JS (srp-js-function-render-runtime) 4087 * could in principle read _highlightResult even though the theme does not. 4088 * ?da-search-payload=full restores the old payload for one request, which 4089 * is the way to test that theory on a live dealer before flipping the switch. 4090 */ 4091 var daTrimSearchPayload = true && new URLSearchParams(window.location.search).get('da-search-payload') !== 'full'; 4092 4093 /** 4094 * Cancel a search the moment a newer one supersedes it. 4095 * 4096 * Michael's idea, confirmed by measurement on Slow 4G: typing "tundra" at 4097 * a normal cadence put EIGHT multi_search requests in flight at once. The 4098 * first two responses ate the whole link (444KB), "tun" through "tundra" 4099 * all hit the client's 5s timeout, were retried, and timed out again - so 4100 * the page settled with the box saying "tundra" and the results showing 4101 * "tu". On a slow connection the stale downloads do not just waste 4102 * transfer, they starve the one query the user actually wants and leave 4103 * wrong results on screen. 4104 * 4105 * The adapter's client sends via axios/XHR, which complicates the obvious 4106 * fix: a bare xhr.abort() fires the error path, axios rejects, and 4107 * typesense-js treats that as a node failure and RETRIES - recreating the 4108 * storm this exists to prevent. So a superseded request is silenced 4109 * before it is aborted: every handler axios attached is stripped, then 4110 * the native abort runs. Axios never learns; its promise simply never 4111 * settles; the retry logic never fires. InstantSearch orders responses by 4112 * query id, so the never-answered request was never going to render 4113 * anyway. 4114 * 4115 * Fast connections are unaffected in practice: responses return in 4116 * ~250ms and are done before the next keystroke, so there is rarely 4117 * anything in flight to cancel. 4118 */ 4119 var daCancelStaleSearch = true && new URLSearchParams(window.location.search).get('da-cancel-stale-search') !== 'off'; 4120 4121 /** 4122 * Arm content-visibility on the result cards (rule in algolia.css, gated 4123 * on this class so the flag lives here with the other Performance flags). 4124 * Off-screen cards then skip style recalculation and layout entirely on 4125 * each render - the two largest named costs in the keystroke trace after 4126 * the render itself. See the comment block in algolia.styl for numbers. 4127 */ 4128 if (true && new URLSearchParams(window.location.search).get('da-content-visibility') !== 'off') { 4129 document.documentElement.classList.add('da-cv'); 4130 } 4131 4132 // The header that marks a request as this SRP's own. Sent by the adapter's 4133 // client (below) and recognised by the canceller; nothing else uses it. 4134 var DA_SRP_SEARCH_HEADER = 'X-DA-SRP-Search'; 4135 4136 if (daCancelStaleSearch) { 4137 (function () { 4138 var inFlight = null; 4139 4140 /** 4141 * Ownership is carried by the request itself, not inferred. 4142 * 4143 * Keying on '/multi_search' alone claimed EVERY Typesense client on 4144 * the page - the inventory-widget shortcode builds its own adapter, 4145 * and one slot shared between it and the SRP meant each aborted the 4146 * other's requests. A silenced request never settles its promise, 4147 * so the loser hung forever: the widget spinning, or the SRP stuck 4148 * in stalled with stale results. 4149 * 4150 * A timing-based claim (a ticket raised beside each search call) 4151 * only narrowed that: our XHR opens several microtasks after the 4152 * call, so a request already mid-chain in another adapter could 4153 * drain the ticket first and invert ownership, and typesense-js 4154 * schedules its retries on a timer, which left every retry 4155 * unclaimable. Both go away if the request announces itself: the 4156 * SRP's client sends DA_SRP_SEARCH_HEADER (see the adapter's server 4157 * config), no other client on the page does, and a retry re-sends 4158 * the same headers. 4159 * 4160 * The header costs no round trips. These requests already carry 4161 * x-typesense-api-key and a JSON content type, so they are already 4162 * preflighted; the endpoint was measured to reflect an arbitrary 4163 * requested header back in access-control-allow-headers, with 4164 * access-control-max-age 3600. 4165 */ 4166 var nativeSend = XMLHttpRequest.prototype.send; 4167 var nativeAbort = XMLHttpRequest.prototype.abort; 4168 var nativeAdd = XMLHttpRequest.prototype.addEventListener; 4169 var nativeRem = XMLHttpRequest.prototype.removeEventListener; 4170 var nativeHeader = XMLHttpRequest.prototype.setRequestHeader; 4171 4172 XMLHttpRequest.prototype.setRequestHeader = function (name, value) { 4173 if (String(name).toLowerCase() === DA_SRP_SEARCH_HEADER.toLowerCase()) { 4174 this.__daSearch = true; 4175 this.__daHandlers = []; 4176 } 4177 return nativeHeader.apply(this, arguments); 4178 }; 4179
4180 // Record what axios attaches to a search request, so it can all be 4181 // detached at supersede time. Non-search requests skip the 4182 // bookkeeping entirely. 4183 XMLHttpRequest.prototype.addEventListener = function (type, fn, opts) { 4184 if (this.__daSearch && this.__daHandlers) { 4185 this.__daHandlers.push([type, fn, opts]); 4186 } 4187 return nativeAdd.apply(this, arguments); 4188 }; 4189 4190 function silence(xhr) { 4191 (xhr.__daHandlers || []).forEach(function (h) { 4192 try { nativeRem.call(xhr, h[0], h[1], h[2]); } catch (e) {} 4193 }); 4194 xhr.__daHandlers = null; 4195 // Older axios wires the on* properties instead of listeners. 4196 xhr.onreadystatechange = xhr.onload = xhr.onerror = null; 4197 xhr.onabort = xhr.ontimeout = xhr.onloadend = xhr.onprogress = null; 4198 try { nativeAbort.call(xhr); } catch (e) {} 4199 } 4200 4201 XMLHttpRequest.prototype.send = function () { 4202 if (this.__daSearch) { 4203 if (inFlight && inFlight !== this) { 4204 silence(inFlight); 4205 } 4206 inFlight = this; 4207 4208 var self = this; 4209 // Attached via the native path so silence() cannot strip it. 4210 nativeAdd.call(this, 'loadend', function () { 4211 if (inFlight === self) { inFlight = null; } 4212 }); 4213 } 4214 return nativeSend.apply(this, arguments); 4215 }; 4216 })(); 4217 } 4218 4219 const typesenseAdapter = new TypesenseInstantSearchAdapter({ 4220 server: { 4221 apiKey: "eQUa8iq30l8Tu908Drz9WKqar6tCJGd4", 4222 nodes: [{ 4223 host: 'hjnrb3s21408ezpfp.a1.typesense.net', 4224 port: 443, 4225 protocol: 'https' 4226 }], 4227 // Marks this client's requests for the stale-search canceller 4228 // above, retries included. Sent only when cancellation is on, so a 4229 // dealer with the switch off sends exactly the old request. 4230 additionalHeaders: daCancelStaleSearch 4231 ? (function () { var h = {}; h[DA_SRP_SEARCH_HEADER] = '1'; return h; })() 4232 : {}, 4233 cacheSearchResultsForSeconds: 2 * 60, 4234 }, 4235 additionalSearchParameters: Object.assign({ 4236 query_by: "vin,stockNumber,lastEight,year,make,model,trim,body,features,engine,transmission,drivetrain,fuel,dealertag,exteriorColor,genericColor", 4237 query_by_weights: "10,10,10,3,8,10,7,2,3,1,2,2,2,2,2,1", 4238 text_match_type: "max_weight", 4239 drop_tokens_mode: "both_sides:3", 4240 drop_tokens_threshold: 1 4241 }, daTrimSearchPayload ? { highlight_fields: "none", highlight_full_fields: "none" } : {}) 4242 }); 4243 4244const searchClient = typesenseAdapter.searchClient; 4245 4246 4247 /** 4248 * Hold result RENDERING until typing pauses. The search itself is not 4249 * delayed - this is the other half of the story the render split started. 4250 * 4251 * The field reports that prompted it (2026-08-21, three iPhone users, 4252 * independently): results arrive fast, but LETTERS appear late. The trace 4253 * agrees: each keystroke's re-render occupies the main thread for roughly 4254 * two seconds on a phone (InstantSearch rebuild + style recalculation 4255 * across ~16,000 elements on live i95), so the NEXT keypress cannot paint 4256 * until the previous render finishes. One user narrated the mechanism 4257 * without knowing it: "once filter(0) is reached, the lag is gone so live 4258 * filtering seems to be lagging input." 4259 * 4260 * So: while keys arrive faster than the settle delay, the queryHook holds 4261 * the QUERY too (see the BURST ADDENDUM there: calling search() moves the 4262 * helper's state and re-renders every widget, main-thread work that the 4263 * gated render handler cannot avoid), and this wrapper holds any RESPONSE 4264 * still in flight when typing resumes. While the user types, nothing 4265 * renders and every keystroke echoes instantly; the moment they pause,
4266 * exactly one search fires and its response renders on arrival. On a slow 4267 * connection that is one round trip after the pause - the accepted price 4268 * of the burst hold, kept honest by cancel-stale above so nothing stale 4269 * competes with it. 4270 * 4271 * Two guards keep it to exactly ONE render per pause: 4272 * - cancel-stale above kills superseded requests at the network layer; 4273 * - the sequence check here refuses to deliver any response that is no 4274 * longer the newest, covering dealers with cancel-stale switched off. 4275 * A refused response returns a promise that never settles, which is also 4276 * how cancel-stale silences axios - InstantSearch's own query 4277 * ordering means it was never going to render anyway. 4278 * 4279 * Quiet threshold shares DA_SETTLE_MS (Theme Options -> Performance -> 4280 * settle delay) so there is one tuning knob for "typing has paused". 4281 */ 4282 var daRenderOnSettle = true && new URLSearchParams(window.location.search).get('da-render-on-settle') !== 'off'; 4283 4284 /** 4285 * -Infinity, not 0: performance.now() starts near zero at page load, so a 4286 * zero here read as "typed just now" for the first DA_SETTLE_MS of page 4287 * life and held the bootstrap render behind whenQuiet() on warm loads. 4288 */ 4289 var daLastTypeAt = -Infinity; 4290 4291 /** 4292 * True while the shopper is mid-burst in the search box. Shared by the 4293 * response hold below and onRenderHandler: while this is true, responses 4294 * are parked, so a render event can only be a loading-state churn against 4295 * results that cannot have changed - and both halves of the handler skip. 4296 */ 4297 function daTypingActive() { 4298 var quiet = (typeof DA_SETTLE_MS === 'number') ? DA_SETTLE_MS : 250; 4299 return (performance.now() - daLastTypeAt) < quiet; 4300 } 4301 4302 if (daRenderOnSettle) { 4303 document.addEventListener('input', function (e) { 4304 if (e.target && e.target.classList && e.target.classList.contains('ais-SearchBox-input')) { 4305 daLastTypeAt = performance.now(); 4306 } 4307 }, true); 4308 4309 (function () { 4310 var seq = 0; 4311 4312 function quietMs() { 4313 return (typeof DA_SETTLE_MS === 'number') ? DA_SETTLE_MS : 250; 4314 } 4315 4316 function whenQuiet(isStale) { 4317 return new Promise(function (resolve) { 4318 (function check() { 4319 // A superseded caller stops polling right away: its 4320 // .then below discards the result, and resolving now 4321 // releases the response object this promise chain was 4322 // pinning (~428KB per keystroke on live i95) instead 4323 // of reforging the closure until typing stops. 4324 if (isStale()) { 4325 resolve(); 4326 return; 4327 } 4328 var since = performance.now() - daLastTypeAt; 4329 if (since >= quietMs()) { 4330 resolve(); 4331 } else { 4332 setTimeout(check, Math.max(16, quietMs() - since)); 4333 } 4334 })(); 4335 }); 4336 } 4337 4338 var origSearch = searchClient.search.bind(searchClient); 4339 4340 searchClient.search = function (requests) { 4341 var mySeq = ++seq; 4342 4343 return origSearch(requests).then(function (res) { 4344 if (mySeq !== seq) { 4345 return new Promise(function () {}); 4346 } 4347 return whenQuiet(function () { return mySeq !== seq; }).then(function () { 4348 if (mySeq !== seq) { 4349 return new Promise(function () {}); 4350 } 4351 return res; 4352 }); 4353 }); 4354 }; 4355 })(); 4356 } 4357function getSrpWindowTitle(refinementList) { 4358 if (!refinementList) { 4359 return srpCondition + " Toyota Vehicles in " + cityState; 4360 } 4361 4362 return srpCondition + " " + buildTitle(refinementList) + " in " + cityState; 4363} 4364 4365function syncSrpSeoState(refinementList) { 4366 $("h1").text(getSrpWindowTitle(refinementList)); 4367 4368 if (refinementList) { 4369 buildDescription(refinementList); 4370 } 4371} 4372 4373const daSrpRouter = instantsearch.routers.history({ 4374 /** 4375 * One history entry per settled search, not one per keystroke. 4376 * 4377 * The router calls history.pushState on every UI-state write, and the 4378 * default 400ms writeDelay is shorter than the gap between keystrokes 4379 * for most people - so typing a six-letter model name pushed six 4380 * entries. That is six Back presses to leave the page, and it walks 4381 * straight at WebKit's history-call rate limit (~100 per 30s, past 4382 * which Safari throws a SecurityError). 1000ms collapses a typed word
4383 * into one or two entries; refinement clicks are spaced well past a 4384 * second apart, so facet navigation keeps an entry per click exactly 4385 * as before. 4386 * 4387 * The debounce has a hole the pagehide flush below plugs: the router 4388 * never flushes a pending write when the page is left, so a shopper 4389 * who filtered and tapped a vehicle inside one writeDelay would come 4390 * Back to an SRP that had forgotten the filter. True at the default 4391 * 400ms too; a full second just made it easy to hit. 4392 */ 4393 writeDelay: 1000, 4394 windowTitle: function windowTitle(routeState) { 4395 syncSrpSeoState(routeState.refinementList); 4396 4397 return getSrpWindowTitle(routeState.refinementList); 4398 }, 4399 createURL: function createURL({ qsModule, location, routeState }) { 4400 const origin = location.origin; 4401 const pathname = location.pathname; 4402 const hash = location.hash; 4403 4404 const urlParams = new URLSearchParams(window.location.search); 4405 const priceBelow = urlParams.get('priceBelow'); 4406 4407 /** 4408 * Params carried onto every URL the router builds. 4409 * 4410 * The query string is rebuilt from route state, so anything the 4411 * router does not model is dropped on every write. utm_* was 4412 * already carried for that reason; the ad click IDs join it, 4413 * because Back from a VDP onto an SRP stripped of its gclid breaks 4414 * attribution for the traffic that costs the most to buy. 4415 * 4416 * Carrying them HERE rather than in the pagehide flush is what 4417 * makes the flush safe. Its first version appended click IDs to 4418 * the finished URL string and split on '#' and '?' to place them, 4419 * which mis-sliced any URL whose refinement values contain those 4420 * characters - and they can, because refinements are serialised 4421 * with encode:false (the exteriorHex strip below exists for the 4422 * same reason). A dealertag of "Certified #1 Dealer" truncated the 4423 * query at the '#' and pushed every later refinement into the 4424 * fragment. Building the URL in one place, from parts, has no 4425 * string surgery to get wrong. 4426 * 4427 * Values are encoded, unlike the raw interpolation below: these 4428 * arrive from ad platforms rather than from our own state, and an 4429 * unencoded one would reintroduce exactly the bug above. 4430 */ 4431 const carriedParams = [ 4432 'utm_campaign', 'utm_medium', 'utm_source', 'utm_term', 'utm_id', 'utm_content', 4433 'gclid', 'gbraid', 'wbraid', 'dclid', 'fbclid', 'msclkid', 'ttclid', 'gad_source', 'srsltid' 4434 ]; 4435 const utmQuery = carriedParams 4436 .map(param => { 4437 const value = urlParams.get(param); 4438 return value ? `${param}=${encodeURIComponent(value)}` : null; 4439 }) 4440 .filter(Boolean) 4441 .join('&'); 4442 4443 const queryParts = []; 4444 4445 if (routeState.refinementList) { 4446 var refinements = Object.assign({}, routeState.refinementList); 4447 // Remove # from exteriorHex values for correct URL formatting 4448 if (refinements.exteriorHex) { 4449 refinements.exteriorHex = refinements.exteriorHex.map(function(v) { return v.replace('#', ''); }); 4450 } 4451 queryParts.push(qsModule.stringify(refinements, { arrayFormat: 'repeat', delimiter: '&', encode: false })); 4452 } 4453 4454 if (routeState.hierarchicalMenu) { 4455 queryParts.push(qsModule.stringify({ modelCategory: routeState.hierarchicalMenu["modelCategory.lvl0"] }, { arrayFormat: 'repeat', delimiter: '&', encode: false })); 4456 } 4457 4458 if (routeState.query) { 4459 queryParts.push(`q=${routeState.query}`); 4460 } 4461 4462 if (routeState.page) { 4463 queryParts.push(`pg=${routeState.page}`); 4464 } 4465 4466 if (routeState.range?.rangeSliderPrice) { 4467 queryParts.push(`priceRange=${routeState.range.rangeSliderPrice}`); 4468 } 4469 if (routeState.range?.mileage) { 4470 queryParts.push(`mileageRange=${routeState.range.mileage}`); 4471 } 4472 if (routeState.range?.yr) { 4473 queryParts.push(`yearRange=${routeState.range.yr}`); 4474 } 4475 4476 if (priceBelow) { 4477 queryParts.push(`priceBelow=${priceBelow}`); 4478 } 4479 4480 let queryString = queryParts.filter(Boolean).join('&'); 4481 4482 if (queryString.includes('transmission_type')) { 4483 queryString = queryString.replace('_type', ''); 4484 } 4485 4486 if (utmQuery) { 4487 queryString = queryString ? `${queryString}&${utmQuery}` : utmQuery; 4488 } 4489 4490 const fullURL = `${origin}${pathname}${queryString ? `?${queryString}` : ''}${hash}`; 4491 4492 return fullURL; 4493 }, 4494 parseURL: function parseURL(_ref2) { 4495 var qsModule = _ref2.qsModule, location = _ref2.location; 4496 var urlSearch = new URLSearchParams(window.location.search); 4497 //Convert the current URL to JSON
4498 let refinements = qsModule.parse(location.search.slice(1), {arrayFormat: 'repeat', delimiter: '&'}); 4499 4500 // Add hashtag back to exteriorHex for correct filtering 4501 if (refinements.exteriorHex) { 4502 refinements.exteriorHex = [].concat(refinements.exteriorHex).map(function(v) { 4503 return v.charAt(0) === '#' ? v : '#' + v; 4504 }); 4505 } 4506 4507 var priceBelow = urlSearch.get('priceBelow'); 4508 if (priceBelow) { 4509 refinements.price = refinements.price || []; 4510 refinements.price.push('<' + priceBelow); 4511 } 4512 4513 //Carousel Model Manipulation 4514 if(refinements['model']) { 4515 4516 if(Array.isArray(refinements['model'])) { 4517 for(let i = 0; i < refinements['model'].length; i++) { 4518 refinements['model'][i] = formatModelName(refinements['model'][i]); 4519 } 4520 }else{ 4521 refinements['model'] = formatModelName(refinements['model']); 4522 } 4523 } 4524 //End Carousel Model Manipulation 4525 4526 if (isNexusToyota && refinements['flags.type'] == "Certified") 4527 { 4528 refinements['flags.type'] = [ 4529 "Gold Certified", 4530 "Silver Certified" 4531 ]; 4532 } else if (isNexusHonda && refinements['flags.type'] == "Certified") 4533 { 4534 refinements['flags.type'] = [ 4535 "True Certified", 4536 "True Used" 4537 ]; 4538 } else if (isNexusAcura && refinements['flags.type'] == "Certified") { 4539 refinements['flags.type'] = [ 4540 "Precision Certified", 4541 "Precision Used" 4542 ]; 4543 } 4544 4545 4546 4547 let refinementsList = refinements; 4548 4549 for (var refinement in refinements) 4550 { 4551 if (typeof refinements[refinement] == "string") 4552 { 4553 refinementsList[refinement] = [refinements[refinement]]; 4554 } 4555 } 4556 4557 const priceRange = urlSearch.get('priceRange'); 4558 const mileageRange = urlSearch.get('mileageRange'); 4559 const yearRange = urlSearch.get('yearRange'); 4560 let range = {}; 4561 4562 if (priceRange) { 4563 range.rangeSliderPrice = priceRange; 4564 } 4565 4566 if (mileageRange) { 4567 range.mileage = mileageRange; 4568 } 4569 4570 if (yearRange) { 4571 range.yr = yearRange; 4572 } 4573 4574 let hierarchicalMenu = {}; 4575 if (refinements['modelCategory']) 4576 { 4577 hierarchicalMenu["modelCategory.lvl0"] = refinements['modelCategory']; 4578 } 4579 4580 //Return the corrected refinement array and current query and page (if exists) 4581 return { 4582 refinementList: refinementsList, 4583 query: urlSearch.get('q'), 4584 page: urlSearch.get('pg'), 4585 range: range, 4586 hierarchicalMenu: hierarchicalMenu 4587 } 4588 } 4589 }); 4590 4591 /** 4592 * Commit the debounced URL write before the page goes away. 4593 * 4594 * The history router schedules its history write on a writeDelay timer and 4595 * never flushes it on unload (verified in the instantsearch.js bundle), so 4596 * any navigation inside the delay - filter, tap a vehicle, Back - landed on 4597 * an SRP without the filter. 4598 * 4599 * REPLACE, never push. The entry being fixed up is the SRP the shopper is 4600 * leaving, so the correction belongs ON it: pushing would leave the 4601 * filtered SRP in front of the unfiltered one and cost a second Back press 4602 * to escape, which is the exact tax the writeDelay change set out to 4603 * remove. It also sidesteps the browser-dependent question of where an 4604 * entry pushed during pagehide lands relative to the committing navigation. 4605 * 4606 * The URL is captured at write() time rather than rebuilt at pagehide, 4607 * because that is the moment the router computes its own - only the history 4608 * call is debounced - so what is written is byte-identical to what would 4609 * have been. It is also written UNTOUCHED: click IDs are carried by 4610 * createURL now, so there is no string surgery here to get wrong on a 4611 * refinement value containing '#' or '?'. 4612 * 4613 * pagehide rather than beforeunload: it fires only when the page is really 4614 * being left, so a cancelled navigation cannot rewrite the URL underneath a 4615 * shopper who stayed. 4616 * 4617 * ?da-url-flush=off disables it for one request. It is the only behaviour 4618 * in this PR that writes browser history during unload, so it gets the same 4619 * escape hatch as everything else here even though it is a bug fix. 4620 */ 4621 if (new URLSearchParams(window.location.search).get('da-url-flush') !== 'off') { 4622 (function () {
4623 var pendingUrl = null; 4624 var nativeWrite = daSrpRouter.write.bind(daSrpRouter); 4625 4626 daSrpRouter.write = function (routeState) { 4627 pendingUrl = daSrpRouter.createURL(routeState); 4628 return nativeWrite(routeState); 4629 }; 4630 4631 window.addEventListener('pagehide', function () { 4632 if (pendingUrl === null || pendingUrl === window.location.href) { 4633 return; // nothing pending, or the debounced write already ran 4634 } 4635 4636 try { 4637 history.replaceState(null, '', pendingUrl); 4638 } catch (e) { /* WebKit's history rate limit; nothing left to try */ } 4639 }); 4640 })(); 4641 } 4642 4643const search = instantsearch({indexName: indexName, stalledSearchDelay: 1000, searchClient: searchClient, searchParameters: { clickAnalytics: true }, routing: {router: daSrpRouter, stateMapping: { 4644 stateToRoute: function stateToRoute(uiState) { 4645 //Update routeState with current uiState 4646 return { 4647 query: uiState[indexName].query, 4648 page: uiState[indexName].page, 4649 refinementList: uiState[indexName].refinementList, 4650 range: uiState[indexName].range, 4651 hierarchicalMenu: uiState[indexName].hierarchicalMenu 4652 }; 4653 }, 4654 routeToState: function routeToState(routeState) { 4655 //Update uiState with current routeState 4656 return { 4657 "vehicles-TOY32136": { 4658 query: routeState.query, 4659 page: routeState.page, 4660 refinementList: routeState.refinementList, 4661 range: routeState.range, 4662 hierarchicalMenu: routeState.hierarchicalMenu 4663 } 4664 }; 4665 } 4666 }}}); 4667 4668 const urlParams = new URLSearchParams(window.location.search); 4669 const priceBelow = urlParams.get('priceBelow'); 4670 4671 let setFilters = ''; 4672 if (priceBelow) { 4673 setFilters = `condition:${srpCondition} && finalPriceInt:<${priceBelow}`; 4674 } else { 4675 setFilters = "condition:" + srpCondition; 4676 } 4677 4678 //Main Search Widget 4679 search.addWidgets([ 4680 instantsearch.widgets.configure({ 4681 filters: setFilters, 4682 hitsPerPage: 24 4683 }) 4684 ]); 4685 4686 4687 //Results Widget 4688 search.addWidgets([ 4689 instantsearch.widgets.hits({ 4690 container: '#srp-results', 4691 templates: { 4692 item: document.getElementById('hit-template').innerHTML, 4693 empty: document.getElementById('empty-template').innerHTML 4694 }, 4695 transformItems(items) { 4696 const transformedItems = items.map(item => transformIncentives(item)); 4697 vehiclesList = items; 4698 return items; 4699 } 4700 }) 4701 ]); 4702 4703 // Listen for the render event 4704 search.on('render', () => { 4705 _triggerInventoryLoaded(); 4706 // You can add any post-render logic here 4707 }); 4708 4709 //Banner Widget for TOP of srp 4710 4711 //Text Search Widget 4712 search.addWidget( 4713 instantsearch.widgets.searchBox({ 4714 container: "#searchbox", 4715 placeholder: "Search Inventory", 4716 autofocus: false, 4717 showLoadingIndicator: true, 4718 queryHook: function(query, search){ 4719 4720 query = query.replace(/(\b\d\b)\s+(?=\w)/g, '$1'); 4721 4722 if(query?.length == 0 || query == undefined){ 4723 document.querySelector('#clearSearchResults').style.display = "none"; 4724 } else { 4725 document.querySelector('#clearSearchResults').style.display = "block"; 4726 } 4727 4728 /** 4729 * Coalesce keystrokes into one search. 4730 * 4731 * Each search replaces the whole results list - about 3,400 nodes - 4732 * and every third-party observer watching body or document is handed 4733 * that entire record set. Firing per character multiplied that by the 4734 * length of the word. 4735 * 4736 * 100ms is deliberately short: it is below the ~150ms where typing 4737 * starts to feel laggy, so results still land while the user is 4738 * typing, but a burst within one word collapses into a single render. 4739 * Clearing the box is exempt so the reset stays instant. 4740 * 4741 * BURST ADDENDUM (2026-08-21, the iPhone keystroke-echo reports). 4742 * Even with the render-on-settle response hold, calling search() 4743 * per keystroke costs: every call moves the helper's state, and 4744 * InstantSearch re-renders every widget against it - measured at 4745 * ~4.7s of main-thread work across one fast-typed word on the 4746 * 4x-throttled bench, none of it produced by our render handler 4747 * (the A/B with the handler gated read the same). So while keys 4748 * are arriving faster than the settle delay, the timer re-arms 4749 * instead of firing: a fast burst reaches the helper as ONE 4750 * search when the fingers pause, and a deliberate typist whose 4751 * gaps exceed the settle delay gets the old per-keystroke flow 4752 * untouched. Gated on the same switch as the response hold - 4753 * they are two halves of "nothing renders mid-burst". 4754 */ 4755 if (window.__dvSearchDebounce) { 4756 clearTimeout(window.__dvSearchDebounce); 4757 } 4758 4759 if (!query) { 4760 // Clearing must reset instantly, as promised above - but 4761 // the backspace that emptied the box also bumped 4762 // daLastTypeAt, which would hold the reset render behind 4763 // the settle delay. Declare typing over instead. 4764 daLastTypeAt = -Infinity; 4765 search(query); 4766 return; 4767 } 4768 4769 var daFireSearch = function () {
4770 if (daRenderOnSettle && daTypingActive()) { 4771 window.__dvSearchDebounce = setTimeout(daFireSearch, 100); 4772 return; 4773 } 4774 search(query); 4775 }; 4776 4777 window.__dvSearchDebounce = setTimeout(daFireSearch, 100); 4778 } 4779 }) 4780 ); 4781 4782 //5-2-2023 customer default sorting work around while we build to admin panel 4783 let currentIndex = 'vehicles-TOY32136'; 4784 currentIndex = currentIndex.split('/')[0]; 4785 4786 //Sort By Widget Desktop 4787 const { connectSortBy } = instantsearch.connectors; 4788 const renderSortByDesktop = (renderOptions, isFirstRender) => { 4789 const { 4790 options, 4791 currentRefinement, 4792 refine, 4793 widgetParams, 4794 // `canRefine` is only available from v4.45.0 4795 // Use `hasNoResults` in earlier minor versions. 4796 canRefine, 4797 } = renderOptions; 4798 4799 if (isFirstRender) { 4800 const _div = document.createElement('div'); 4801 _div.classList.add("dv-srp-sort-desktop"); 4802 4803 _div.innerHTML = ` 4804 ${options.map(option => 4805 `<a data-sort-value="${option.value}" data-sort-label="${option.label}" class="${option.value === currentRefinement ? 'dv-srp-sort-selected' : ''}"> 4806 <i class="fas fa-${option.icon}"></i> ${option.label} 4807 </a>`).join('') 4808 } 4809 `; 4810 let filtered = options.filter(opt => opt.value === currentRefinement); 4811 if(filtered?.length > 0){ 4812 document.querySelector('.dv-srp-search-options-dynamic-label').innerHTML = filtered[0].label; 4813 } 4814 widgetParams.container.appendChild(_div); 4815 } 4816 4817 //widgetParams.container.querySelector('div'); 4818 const nodes = document.querySelectorAll('.dv-srp-sort-desktop > *'); 4819 nodes.forEach(function(node) { 4820 node.addEventListener('click', function(event) { 4821 event.preventDefault(); 4822 if (event?.target == undefined) { return }; 4823 let _ActiveClass = 'dv-srp-sort-selected'; 4824 let _value = event?.target?.dataset?.sortValue; 4825 let _label = event?.target?.dataset?.sortLabel; 4826 4827 if (_value && _value != currentRefinement) { 4828 refine(_value); 4829 if(currentRefinement){ 4830 nodes.forEach(el => el.classList.remove(_ActiveClass)); 4831 event?.target?.classList.add(_ActiveClass); 4832 document.querySelector('.dv-srp-search-options-dynamic-label').innerHTML = _label; 4833 } 4834 } 4835 }); 4836 }); 4837 4838 }; 4839 // Create the custom widget 4840 const customSortByDesktop = connectSortBy(renderSortByDesktop); 4841 search.addWidgets([ 4842 customSortByDesktop({ 4843 container: document.querySelector('#sortByDesktop'), 4844 items: [ 4845 { label: "Most Relevant", value: `${currentIndex}`, icon: 'sort'}, 4846 { label: "Price Low to High", value: `${currentIndex}/sort/sortPrice:desc,price:asc`, icon: 'sort-numeric-down'}, 4847 { label: "Price High to Low", value: `${currentIndex}/sort/sortPrice:desc,price:desc`, icon: 'sort-numeric-up'}, 4848 { label: distanceUnit + 's Low to High', value: `${currentIndex}/sort/mileage:asc`, icon: 'sort-numeric-down'}, 4849 { label: "Year: Newest", value: `${currentIndex}/sort/yr:desc`, icon: 'long-arrow-up'}, 4850 { label: "Year: Oldest", value: `${currentIndex}/sort/yr:asc`, icon: 'long-arrow-down'} 4851 ], 4852 }) 4853 ]); 4854 4855 // Toggle Desktop Sort Dropdown 4856 document.querySelector('#sortByDesktop').addEventListener('click', function(event) { 4857 event.stopPropagation(); 4858 var el = document.querySelector('.dv-srp-sort-desktop'); 4859 el.classList.toggle('dv-srp-sort-desktop-active'); 4860 }); 4861 4862 // Close dropdown when clicking outside 4863 document.addEventListener('click', function(event) { 4864 var el = document.querySelector('.dv-srp-sort-desktop'); 4865 var button = document.querySelector('#sortByDesktop'); 4866 4867 if (!el.contains(event.target) && !button.contains(event.target)) { 4868 el.classList.remove('dv-srp-sort-desktop-active'); 4869 } 4870 }); 4871 4872 //Sort By Widget Mobile 4873 const renderSortByMobile = (renderOptions, isFirstRender) => { 4874 const { 4875 options, 4876 currentRefinement, 4877 refine, 4878 widgetParams, 4879 // `canRefine` is only available from v4.45.0 4880 // Use `hasNoResults` in earlier minor versions. 4881 canRefine, 4882 } = renderOptions; 4883 4884 if (isFirstRender) { 4885 const _div = document.createElement('div'); 4886 _div.classList.add("dv-srp-sort-mobile"); 4887 4888 _div.innerHTML = ` 4889 ${options.map(option => 4890 `<a data-sort-value="${option.value}" data-sort-label="${option.label}" class="${option.value === currentRefinement ? 'dv-srp-sort-selected' : ''}"> 4891 <i class="fas fa-${option.icon}"></i> ${option.label} 4892 </a>`).join('') 4893 } 4894 `; 4895 4896 widgetParams.container.appendChild(_div); 4897 } 4898 4899 //widgetParams.container.querySelector('div'); 4900 const nodes = document.querySelectorAll('.dv-srp-sort-mobile > *');
4901 nodes.forEach(function(node) { 4902 node.addEventListener('click', function(event) { 4903 event.preventDefault(); 4904 if (event?.target == undefined) { return }; 4905 let _ActiveClass = 'dv-srp-sort-selected'; 4906 let _value = event?.target?.dataset?.sortValue; 4907 let _label = event?.target?.dataset?.sortLabel; 4908 4909 if (_value && _value != currentRefinement) { 4910 refine(_value); 4911 if(currentRefinement){ 4912 nodes.forEach(el => el.classList.remove(_ActiveClass)); 4913 event?.target?.classList.add(_ActiveClass); 4914 } 4915 } 4916 }); 4917 }); 4918 4919 }; 4920 // Create the custom widget 4921 const customSortByMobile = connectSortBy(renderSortByMobile); 4922 search.addWidgets([ 4923 customSortByMobile({ 4924 container: document.querySelector('#sortByMobile'), 4925 items: [ 4926 { label: "Most Relevant", value: `${currentIndex}`, icon: 'sort'}, 4927 { label: "Price Low to High", value: `${currentIndex}/sort/sortPrice:desc,price:asc`, icon: 'sort-numeric-down'}, 4928 { label: "Price High to Low", value: `${currentIndex}/sort/sortPrice:desc,price:desc`, icon: 'sort-numeric-up'}, 4929 { label: distanceUnit + 's Low to High', value: `${currentIndex}/sort/mileage:asc`, icon: 'sort-numeric-down'}, 4930 { label: "Year: Newest", value: `${currentIndex}/sort/yr:desc`, icon: 'long-arrow-up'}, 4931 { label: "Year: Oldest", value: `${currentIndex}/sort/yr:asc`, icon: 'long-arrow-down'} 4932 ], 4933 }) 4934 ]); 4935 4936 // Toggle Mobile Sort Dropdown 4937 document.querySelector('#sortByMobile').addEventListener('click', function(event) { 4938 event.stopPropagation(); // Prevent the event from bubbling up to the document 4939 var el = document.querySelector('.dv-srp-sort-mobile'); 4940 el.classList.toggle('dv-srp-sort-mobile-active'); 4941 }); 4942 4943 // Close dropdown when clicking outside 4944 document.addEventListener('click', function(event) { 4945 var el = document.querySelector('.dv-srp-sort-mobile'); 4946 var button = document.querySelector('#sortByMobile'); 4947 4948 if (!el.contains(event.target) && !button.contains(event.target)) { 4949 el.classList.remove('dv-srp-sort-mobile-active'); 4950 } 4951 }); 4952 search.addWidget( 4953 instantsearch.widgets.rangeSlider({ 4954 container: '#price-range-slider', 4955 attribute: 'rangeSliderPrice', 4956 step: 1000, 4957 pips: false, 4958 precision: 0, 4959 tooltips: { 4960 format(value) { 4961 4962 const newValue = Math.round(value/1000)*1000 4963 return "$" + Math.round(newValue).toLocaleString(); 4964 }, 4965 }, 4966 }) 4967 ); 4968 4969 //Pin price ammounts to top and let handler move them 4970 const priceSlider = document.querySelector('#price-range-slider'); 4971 4972 if (priceSlider) { 4973 /** 4974 * Rheostat positions its handles by writing style.left, so the tooltips 4975 * have to be repositioned in response. Watching for that write is fine; 4976 * doing it naively is not, and the naive version was measurably the most 4977 * expensive observer on this page. 4978 * 4979 * Two problems it had: 4980 * 4981 * 1. It observed style attributes across the slider's whole subtree and 4982 * then wrote styles to the tooltips *inside* that subtree, so every 4983 * run scheduled another run. It only ever settled because the values 4984 * converged. 4985 * 2. It read offsetWidth and then wrote, synchronously, on every single 4986 * mutation - a forced layout each time. Typing in the SRP search box 4987 * re-renders the results and fires this constantly. 4988 * 4989 * So: coalesce to one run per frame, and disconnect around our own writes 4990 * so they cannot feed back in. Skipping unchanged values keeps us from 4991 * dirtying style for no reason. 4992 */ 4993 const OBSERVE_OPTIONS = { 4994 childList: true, 4995 subtree: true, 4996 attributes: true, 4997 attributeFilter: ['style'] 4998 }; 4999 5000 const setStyle = (el, prop, value) => { 5001 if (el.style[prop] !== value) { 5002 el.style[prop] = value; 5003 } 5004 }; 5005 5006 const applyTooltipPositions = () => { 5007 const handles = priceSlider.querySelectorAll('.rheostat-handle'); 5008 5009 if (handles.length !== 2) { 5010 return; 5011 } 5012 5013 const tooltip1 = handles[0].querySelector('.rheostat-tooltip'); 5014 const tooltip2 = handles[1].querySelector('.rheostat-tooltip'); 5015 const background = priceSlider.querySelector('.rheostat-background'); 5016 5017 if (!tooltip1 || !tooltip2 || !background) { 5018 return; 5019 } 5020
5021 // every read first, then every write - one layout pass, not two 5022 const handle1Left = parseFloat(handles[0].style.left) || 0; 5023 const handle2Left = parseFloat(handles[1].style.left) || 100; 5024 const sliderWidth = background.offsetWidth; 5025 5026 const handle1Offset = (handle1Left / 100) * sliderWidth; 5027 const handle2Offset = (handle2Left / 100) * sliderWidth; 5028 5029 setStyle(tooltip1, 'left', `-${handle1Offset}px`); 5030 setStyle(tooltip1, 'transform', 'none'); 5031 5032 setStyle(tooltip2, 'right', `-${sliderWidth - handle2Offset}px`); 5033 setStyle(tooltip2, 'left', 'auto'); 5034 setStyle(tooltip2, 'transform', 'none'); 5035 }; 5036 5037 let repositionQueued = false; 5038 5039 const scheduleReposition = () => { 5040 if (repositionQueued) { 5041 return; 5042 } 5043 5044 repositionQueued = true; 5045 5046 requestAnimationFrame(() => { 5047 repositionQueued = false; 5048 // Detach first: the writes below land inside the observed subtree 5049 // and would otherwise queue another callback immediately. 5050 observer.disconnect(); 5051 5052 try { 5053 applyTooltipPositions(); 5054 } finally { 5055 observer.observe(priceSlider, OBSERVE_OPTIONS); 5056 } 5057 }); 5058 }; 5059 5060 const observer = new MutationObserver(scheduleReposition); 5061 observer.observe(priceSlider, OBSERVE_OPTIONS); 5062 5063 scheduleReposition(); 5064 5065 window.addEventListener('resize', scheduleReposition); 5066 } 5067 var daFacetLimit = 100000; 5068 var daFacetShowMore = false; 5069 var daFacetShowMoreLimit = 100000; 5070 var daFacetSortLead = []; 5071 search.addWidget( 5072 instantsearch.widgets.refinementList({ 5073 container: '#make-list', 5074 attribute: 'make', 5075 operator: 'or', 5076 sortBy: daFacetSortLead.concat(['count:desc']), 5077 limit: daFacetLimit, 5078 showMore: daFacetShowMore, 5079 showMoreLimit: daFacetShowMoreLimit 5080 }) 5081 ); 5082 5083 function renderChildren(items, parent, shouldDisplay) 5084 { 5085 return items.map((item) => { 5086 const isRefined = item.isRefined ? 'ais-RefinementList-item--selected' : ''; 5087 5088 return ` 5089 <li class="ais-RefinementList-item ${isRefined} da-TierRefinementList-child" ${shouldDisplay ? "" : `style="display: none;`} data-parent=${parent}> 5090 <label class="ais-RefinementList-label"> 5091 <input type="checkbox" 5092 class="ais-RefinementList-checkbox" 5093 value="${item.value}" 5094 ${item.isRefined ? 'checked' : ''} 5095 /> 5096 <span class="ais-RefinementList-labelText">${item.label.split(" > ")[1]}</span> 5097 <span class="ais-RefinementList-count">${item.count}</span> 5098 </label> 5099 </li> 5100 `; 5101 }).join(""); 5102 } 5103 5104 // Define a function to recursively render the menu items 5105 function renderItems(items, parentStructure) 5106 { 5107 // In order to sort the menu, you can try sorting items here by item.label before ">" character 5108 if (!items || !parentStructure) 5109 { 5110 return; 5111 } 5112 5113 return parentStructure.map((parent, index) => { 5114 const childrenHitCount = parent.children.reduce((acc, val) => { 5115 return acc + val.count; 5116 }, 0); 5117 5118 const shouldDisplayChildren = parent.children.filter((child) =>
5118 child.isRefined).length > 0; 5119 5120 return `<li class="ais-RefinementList-item da-TierRefinementList-parent" data-parent="${parent.parent}"> 5121 <div> 5122 <label class="ais-RefinementList-label"> 5123 <span class="ais-RefinementList-labelText">${parent.parent}</span> 5124 <span class="ais-RefinementList-count">${childrenHitCount}</span> 5125 </label> 5126 </div> 5127 </li> 5128 ${renderChildren(parent.children, parent.parent, shouldDisplayChildren)} 5129 `; 5130 }) 5131 .join(''); 5132 }; 5133 5134 function getParentChildRelations(items) 5135 { 5136 const itemParents = (items && items.length > 0) ? [ ...new Set(items.map((i) => i.value.split(" > ")[0])) ] : []; 5137 const outStructure = []; 5138 5139 for (let i = 0; i < itemParents.length; i++) 5140 { 5141 const children = items.filter((entry) => entry.value.includes(`${itemParents[i]} >`)); 5142 5143 if (children && children.length > 0) 5144 { 5145 outStructure.push({ 5146 parent: itemParents[i], 5147 children: children 5148 }); 5149 } 5150 } 5151 5152 return outStructure; 5153 } 5154 5155 function renderMultiSelectHierarchicalMenu(renderOptions, isFirstRender) 5156 {
5157 const { items, refine, widgetParams } = renderOptions; 5158 5159 if (isFirstRender) 5160 { 5161 const ul = document.createElement("ul"); 5162 ul.innerHTML = '<div class="ais-RefinementList-list"></div>'; 5163 5164 widgetParams.container.appendChild(ul); 5165 } 5166 5167 const parentChild = getParentChildRelations(items); 5168 5169 const listContainer = widgetParams.container.querySelector('ul'); 5170 listContainer.innerHTML = `<ul class="ais-RefinementList-list da-TierRefinementList-root">${renderItems(items, parentChild)}</ul>`; 5171 5172 widgetParams.container.querySelectorAll('input[type="checkbox"]').forEach(checkbox => { 5173 checkbox.addEventListener('change', event => { 5174 event.preventDefault(); 5175 refine(event.target.value); 5176 }); 5177 }); 5178 5179 widgetParams.container.querySelectorAll(".da-TierRefinementList-parent").forEach(parent => { 5180 event.preventDefault(); 5181 parent.addEventListener("click", event => { 5182 const childValues = parentChild.find(data => data.parent == parent.dataset.parent).children.map((child) => child.value); 5183 5184 for (let i = 0; i < childValues.length; i++) 5185 { 5186 refine(childValues[i]); 5187 } 5188 }); 5189 }) 5190 }; 5191 5192 const multiSelectHierarchicalMenu = instantsearch.connectors.connectRefinementList(renderMultiSelectHierarchicalMenu); 5193 5194 5195 search.addWidget([ 5196 multiSelectHierarchicalMenu({ 5197 container: document.querySelector("#modelCategory-list"), 5198 attribute: "modelCategory.lvl1", 5199 limit: 100000, 5200 operator: "or", 5201 sortBy(a,b) { 5202 a = a.name.toLowerCase(); 5203 b = b.name.toLowerCase(); 5204 5205 if ( a == b ) return 0; 5206 5207 return a < b ? -1 : 1; 5208 }, 5209 transformItems(items) { 5210 return items.filter(item => item.count > 0); 5211 } 5212 }) 5213 ]); 5214 search.addWidget( 5215 instantsearch.widgets.refinementList({ 5216 container: '#trim-list', 5217 attribute: 'trim', 5218 operator: 'or', 5219 sortBy: daFacetSortLead.concat(['count:desc']), 5220 limit: daFacetLimit, 5221 showMore: daFacetShowMore, 5222 showMoreLimit: daFacetShowMoreLimit 5223 }) 5224 ); 5225 search.addWidget( 5226 instantsearch.widgets.refinementList({ 5227 container: '#year-list', 5228 attribute: 'yr', 5229 operator: 'or', 5230 sortBy: daFacetSortLead.concat(['name:desc']), 5231 limit: daFacetLimit, 5232 showMore: daFacetShowMore, 5233 showMoreLimit: daFacetShowMoreLimit 5234 }) 5235 ); 5236 search.addWidget( 5237 instantsearch.widgets.refinementList({ 5238 container: '#pricerange-list', 5239 attribute: 'finalPriceRange', 5240 operator: 'or', 5241 sortBy: function sortBy(a, b) { 5242 let priceOptions = { 5243 "$10,000 and Below": 0, 5244 "$10,000 - $20,000": 1, 5245 "$20,000 - $30,000": 2, 5246 "$30,000 - $40,000": 3, 5247 "$40,000 - $50,000": 4, 5248 "$50,000 - $60,000": 5, 5249 "$60,000 - $70,000": 6, 5250 "$70,000 - $80,000": 7, 5251 "$80,000 - $90,000": 8, 5252 "$90,000 - $100,000": 9, 5253 "$100,000 and Up": 10 5254 }; 5255 5256 if (priceOptions[a.name] < priceOptions[b.name]) 5257 { 5258 return -1; 5259 } 5260 5261 if (priceOptions[a.name] > priceOptions[b.name]) 5262 { 5263 return 1; 5264 } 5265 5266 return 0; 5267 }, 5268 limit: 100000 5269 }) 5270 ); 5271 search.addWidget( 5272 instantsearch.widgets.refinementList({ 5273 container: '#body-list', 5274 attribute: 'body', 5275 operator: 'or', 5276 sortBy: daFacetSortLead.concat(['']), 5277 limit: daFacetLimit, 5278 showMore: daFacetShowMore, 5279 showMoreLimit: daFacetShowMoreLimit, 5280 templates: { 5281 item: "<label class=\"ais-RefinementList-label\">\n\t\t\t\t\t\t\t<input type=\"checkbox\" class=\"ais-RefinementList-checkbox\" value=\"{{value}}\">\n\t\t\t\t\t\t\t<span class=\"ais-RefinementList-labelText srp-{{value}}\">{{value}} · {{count}}</span>\n\t\t\t\t\t\t</label>" 5282 } 5283 }) 5284 ); 5285 5286 // Cab List Widget 5287 search.addWidget( 5288 instantsearch.widgets.refinementList({ 5289 container: '#cab-list', 5290 attribute: 'cab', 5291 operator: 'or', 5292 sortBy: daFacetSortLead.concat(['name:asc']), 5293 limit: daFacetLimit, 5294 showMore: daFacetShowMore, 5295 showMoreLimit: daFacetShowMoreLimit 5296 }) 5297 ); 5298 5299 //Bed List Widget 5300 search.addWidget( 5301 instantsearch.widgets.refinementList({ 5302 container: '#bed-list', 5303 attribute: 'bed', 5304 operator: 'or', 5305 sortBy: daFacetSortLead.concat(['name:asc']), 5306 limit: daFacetLimit, 5307 showMore: daFacetShowMore, 5308 showMoreLimit: daFacetShowMoreLimit 5309 }) 5310 ); 5311 search.addWidget( 5312 instantsearch.widgets.refinementList({ 5313 container: '#fuel-list', 5314 attribute: 'fuel', 5315 operator: 'or', 5316 sortBy: daFacetSortLead.concat(['count:desc']), 5317 limit: daFacetLimit, 5318 showMore: daFacetShowMore, 5319 showMoreLimit: daFacetShowMoreLimit 5320 }) 5321 ); 5322 search.addWidget( 5323 instantsearch.widgets.refinementList({ 5324 container: '#transmission-list', 5325 attribute: 'transmissionType', 5326 operator: 'or', 5327 sortBy: daFacetSortLead.concat(['count:desc']), 5328 limit: daFacetLimit, 5329 showMore: daFacetShowMore, 5330 showMoreLimit: daFacetShowMoreLimit 5331 }) 5332 ); 5333 search.addWidget( 5334 instantsearch.widgets.refinementList({ 5335 container: '#drivetrain-list', 5336 attribute: 'drivetrain', 5337 operator: 'or', 5338 sortBy: daFacetSortLead.concat(['count:desc']), 5339 limit: daFacetLimit, 5340 showMore: daFacetShowMore, 5341 showMoreLimit: daFacetShowMoreLimit, 5342 transformItems(items) { 5343 return items.filter((i) => i.value !== ""); 5344 } 5345 }) 5346 ); 5347 search.addWidget( 5348 instantsearch.widgets.refinementList({ 5349 container: '#location-list', 5350 attribute: 'dealerName', 5351 operator: 'or', 5352 sortBy: ['count:desc'], 5353 limit: 500 5354 }) 5355 ); 5356 search.addWidget( 5357 instantsearch.widgets.refinementList({ 5358 container: '#mpg-hway-list', 5359 attribute: 'mpgHwayRange', 5360 operator: 'or', 5361 sortBy: ['count:desc'], 5362 }) 5363 ); 5364 search.addWidget( 5365 instantsearch.widgets.refinementList({ 5366 container: '#mpg-city-list', 5367 attribute: 'mpgCityRange', 5368 operator: 'or', 5369 sortBy: ['count:desc'], 5370 }) 5371 ); 5372 search.addWidget( 5373 instantsearch.widgets.refinementList({ 5374 container: '#features-list', 5375 attribute: 'features', 5376 operator: 'and', 5377 sortBy: daFacetSortLead.concat(['name:acs']), 5378 limit: daFacetLimit, 5379 showMore: daFacetShowMore, 5380 showMoreLimit: daFacetShowMoreLimit 5381 }) 5382 ); 5383 search.addWidget( 5384 instantsearch.widgets.refinementList({ 5385 container: '#range-list', 5386 attribute: 'range', 5387 operator: 'or', 5388 sortBy: ['count:desc'], 5389 limit: 100000 5390 }) 5391 ); 5392 5393 5394 /* 5395 * 5396 * OEMs require the following order for vehicle Status - NEX-1762 5397 * 5398 */ 5399 const oemStatusOrder = ["In Stock", "In Transit", "In Production"]; 5400 5401 search.addWidget( 5402 instantsearch.widgets.refinementList({ 5403 container: '#status-list', 5404 attribute: 'status', 5405 transformItems(items) { 5406 const sortedItems = [...items].sort((a, b) => { 5407 const indexA = oemStatusOrder.indexOf(a.label); 5408 const indexB = oemStatusOrder.indexOf(b.label); 5409 5410 return (indexA === -1 ? oemStatusOrder.length : indexA) - 5411 (indexB === -1 ? oemStatusOrder.length : indexB); 5412 }); 5413 5414 return sortedItems; // Ensure it returns a new array 5415 }, 5416 templates: { 5417 item: `<label class="ais-RefinementList-label"> 5418 <input type="checkbox" class="ais-RefinementList-checkbox" value="{{value}}"> 5419 <div>
5420 <span class="ais-RefinementList-labelText">{{label}}</span> 5421 </div> 5422 <span class="ais-RefinementList-count">{{count}}</span> 5423 </label>` 5424 } 5425 }) 5426 ); 5427 5428 //Type List Widget 5429 search.addWidget( 5430 instantsearch.widgets.refinementList({ 5431 container: '#type-list', 5432 attribute: 'flags.type', 5433 operator: 'or', 5434 sortBy: daFacetSortLead.concat(['count:desc']), 5435 limit: daFacetLimit, 5436 showMore: daFacetShowMore, 5437 showMoreLimit: daFacetShowMoreLimit 5438 }) 5439 ); 5440 5441 search.addWidget( 5442 instantsearch.widgets.refinementList({ 5443 container: '#dealertag-list', 5444 attribute: 'dealertag', 5445 operator: 'or', 5446 limit: daFacetLimit, 5447 showMore: daFacetShowMore, 5448 showMoreLimit: daFacetShowMoreLimit 5449 }) 5450 ); 5451 5452 5453 //Custom Pagination SRP 5454 const { connectPagination } = instantsearch.connectors; 5455 5456 const renderPagination = (renderOptions, isFirstRender) => { 5457 const { 5458 pages, 5459 currentRefinement, 5460 nbPages, 5461 isFirstPage, 5462 isLastPage, 5463 refine, 5464 createURL, 5465 } = renderOptions; 5466 5467 const container = document.querySelector('#pagination-top'); 5468 5469 if (nbPages <= 1) { 5470 container.style.display = 'none'; 5471 return; 5472 } else { 5473 container.style.display = ''; 5474 } 5475 5476 container.innerHTML = ` 5477 <ul class="ais-pagination-ul"> 5478 ${ 5479 currentRefinement >= 1 5480 ? ` 5481 <li> 5482 <a class="ais-Pagination-link" href="${createURL(currentRefinement - 1)}" data-value="${currentRefinement - 1}"> 5483 <i class="fa-solid fa-chevron-left"></i> 5484 </a> 5485 </li> 5486 ` 5487 : '' 5488 } 5489 <div class="ais-pagination-wrapper"> 5490 Page <span class="ais-Pagination-link">${currentRefinement + 1}</span> of <span class="ais-Pagination-link">${nbPages}</span> 5491 </div> 5492 ${ 5493 currentRefinement < nbPages - 1 5494 ? ` 5495 <li> 5496 <a class="ais-Pagination-link" href="${createURL(currentRefinement + 1)}" data-value="${currentRefinement + 1}"> 5497 <i class="fa-solid fa-chevron-right"></i> 5498 </a> 5499 </li> 5500 ` 5501 : '' 5502 } 5503 </ul> 5504 `; 5505 5506 [...container.querySelectorAll('a')].forEach(element => { 5507 element.addEventListener('click', event => { 5508 event.preventDefault(); 5509 refine(event.currentTarget.dataset.value); 5510 5511 window.scrollTo({ 5512 top: 0, 5513 left: 0, 5514 behavior: 'smooth' 5515 }); 5516 }); 5517 }); 5518 }; 5519 5520 const customPagination = connectPagination( 5521 renderPagination 5522 ); 5523 5524 search.addWidgets([ 5525 customPagination({ 5526 container: document.querySelector('#pagination-top'), 5527 }) 5528 ]); 5529 5530 //Bottom Pagination 5531 5532 const renderPaginationBottom = (renderOptions, isFirstRender) => { 5533 const { 5534 pages, 5535 currentRefinement, 5536 nbPages, 5537 isFirstPage, 5538 isLastPage, 5539 refine, 5540 createURL, 5541 } = renderOptions; 5542 5543 const containerBottom= document.querySelector('#pagination-bottom'); 5544 5545 if (nbPages <= 1) { 5546 containerBottom.style.visibility = 'hidden'; 5547 return; 5548 } else { 5549 containerBottom.style.visibility = 'visible'; 5550 } 5551 5552 containerBottom.innerHTML = ` 5553 <ul class="ais-pagination-ul"> 5554 ${ 5555 currentRefinement >= 1 5556 ? ` 5557 <li> 5558 <a class="ais-Pagination-link" href="${createURL(currentRefinement - 1)}" data-value="${currentRefinement - 1}"> 5559 <i class="fa-solid fa-chevron-left"></i> 5560 </a> 5561 </li> 5562 ` 5563 : '' 5564 } 5565 <div class="ais-pagination-wrapper"> 5566 Page <span class="ais-Pagination-link">${currentRefinement + 1}</span> of <span class="ais-Pagination-link">${nbPages}</span> 5567 </div> 5568 ${ 5569 currentRefinement < nbPages - 1 5570 ? ` 5571 <li> 5572 <a class="ais-Pagination-link" href="${createURL(currentRefinement + 1)}" data-value="${currentRefinement + 1}"> 5573 <i class="fa-solid fa-chevron-right"></i> 5574 </a> 5575 </li> 5576 ` 5577 : '' 5578 } 5579 </ul> 5580 `; 5581 5582 [...containerBottom.querySelectorAll('a')].forEach(element => { 5583 element.addEventListener('click', event => { 5584 event.preventDefault(); 5585 refine(event.currentTarget.dataset.value); 5586 5587 window.scrollTo({ 5588 top: 0, 5589 left: 0, 5590 behavior: 'smooth' 5591 }); 5592 }); 5593 }); 5594 }; 5595 5596 const customPaginationBottom = connectPagination( 5597 renderPaginationBottom 5598 ); 5599 5600 search.addWidgets([ 5601 customPaginationBottom({ 5602 container: document.querySelector('#pagination-bottom'), 5603 }) 5604 ]); 5605 5606//End Customer Pagination SRP 5607 5608 // Clear Results Button Widget 5609 //search.addWidget( 5610 // instantsearch.widgets.clearRefinements({ 5611 // container: '#clearSearchResults', 5612 // templates: { 5613 // resetLabel: '<i class="fal fa-backspace"></i> <span>Clear<br>Search</span>' 5614 // } 5615 // }) 5616 //); 5617 5618 search.addWidget( 5619 instantsearch.widgets.clearRefinements({ 5620 container: '#dv-srp-clear-filters', 5621 templates: { 5622 resetLabel: 'Clear All' 5623 } 5624 }) 5625 ); 5626 5627 search.addWidget( 5628 instantsearch.widgets.clearRefinements({ 5629 container: '#srp-filters-reset-btn', 5630 templates: { 5631 resetLabel: 'Clear Filters' 5632 } 5633 }) 5634 ); 5635 5636 //Results Stats Widget (Top) 5637 // in {{processingTimeMS}}ms 5638 const { connectStats } = instantsearch.connectors; 5639 5640 let renderStats = (renderOptions, isFirstRender) => { 5641 let { 5642 page, 5643 nbPages, 5644 nbSortedHits, 5645 hitsPerPage, 5646 nbHits, 5647 isLastPage, 5648 } = renderOptions; 5649 5650 const containerStats = document.querySelector('#resultsStats'); 5651 5652 let pageNumber = page + 1; 5653 let lastPage = nbPages - 1; 5654 let nextPage = page + 1; 5655 5656 containerStats.innerHTML =` 5657 <div class="ais-Stats"> 5658 ${nbHits === 0 ?`
5659 \n\t\t\t\t\tNo results\n\t\t\t\t\t 5660 ` : '' } 5661 ${page === 0 && nbHits > hitsPerPage ? ` 5662 \n\t\t\t\t\tShowing <span id=\"numberHits\">${pageNumber}</span> - <span id=\"numberHits\">${hitsPerPage * pageNumber}</span> of <span id=\"numberHits\">${nbHits}</span>\n results found\n\t\t\t\t\t` 5663 : ''} 5664 ${page >= 1 && page !== lastPage && nbHits > hitsPerPage ? ` 5665 \n\t\t\t\t\tShowing <span id=\"numberHits\">${page * hitsPerPage}</span> - <span id=\"numberHits\">${hitsPerPage * nextPage}</span> of <span id=\"numberHits\">${nbHits}</span>\n results found\n\t\t\t\t\t 5666 ` : ''} 5667 ${page === lastPage && nbHits < hitsPerPage ? ` 5668 \n\t\t\t\t\tShowing <span id=\"numberHits\">${pageNumber}</span> - <span id=\"numberHits\">${nbHits}</span> of <span id=\"numberHits\">${nbHits}</span>\n results found\n\t\t\t\t\t 5669 ` : ''} 5670 ${page === lastPage && nbPages != 1 ? ` 5671 \n\t\t\t\t\tShowing <span id=\"numberHits\">${lastPage * hitsPerPage}</span> - <span id=\"numberHits\">${nbHits}</span> of <span id=\"numberHits\">${nbHits}</span>\n results found\n\t\t\t\t\t 5672 ` : ''} 5673 `; 5674 5675 }; 5676 5677 const customStats = connectStats( 5678 renderStats 5679 ); 5680 5681 search.addWidgets([ 5682 customStats({ 5683 container: document.querySelector('#resultsStats'), 5684 }) 5685 ]); 5686 5687 //Result Stats Widget (Bottom) 5688 // in {{processingTimeMS}}ms 5689 search.addWidget( 5690 instantsearch.widgets.stats({ 5691 container: '#resultsStats-bottom', 5692 templates: { 5693 text: "\n\t\t\t\t\t{{#hasNoResults}}No results{{/hasNoResults}}\n\t\t\t\t\t{{#hasOneResult}}<span id=\"numberHits\">1</span> result{{/hasOneResult}}\n\t\t\t\t\t{{#hasManyResults}}<span id=\"numberHits\">{{#helpers.formatNumber}}{{nbHits}}{{/helpers.formatNumber}}</span> results{{/hasManyResults}} found" 5694 } 5695 }) 5696 ); 5697 5698 //Mobile Show Filters Buttom Stats Widget 5699 search.addWidget( 5700 instantsearch.widgets.stats({ 5701 container: '#showFiltersNonLegacy', 5702 templates: { 5703 text: "\n\t\t\t\t\t<div class='dv-srp-search-options-wrapper'><span class='showFilters-label'><i class='fas fa-sort-amount-up'></i> Filter</span> <span class='showFilters-value'>{{#hasNoResults}}(0){{/hasNoResults}}\n\t\t\t\t\t{{#hasOneResult}}(1){{/hasOneResult}}\n\t\t\t\t\t{{#hasManyResults}} ({{#helpers.formatNumber}} {{nbHits}} {{/helpers.formatNumber}}) {{/hasManyResults}}</span></div>" 5704 } 5705 }) 5706 ); 5707 search.addWidget( 5708 instantsearch.widgets.stats({ 5709 container: '#srpFilterResultCount', 5710 templates: { 5711 text: "\n\t\t\t\t\t{{#hasNoResults}}No Results{{/hasNoResults}}\n\t\t\t\t\t{{#hasOneResult}}Show 1 Result{{/hasOneResult}}\n\t\t\t\t\t{{#hasManyResults}}Show {{#helpers.formatNumber}}{{nbHits}}{{/helpers.formatNumber}} Results{{/hasManyResults}}" 5712 } 5713 }) 5714 ); 5715 5716 search.addWidget( 5717 instantsearch.widgets.currentRefinements({ 5718 container: '#filterTags', 5719 transformItems: function transformItems(items) { 5720 items.forEach(function (item) { 5721 if (item.label == "dealer.name") 5722 { 5723 item.label = "Dealer Name"; 5724 }; 5725 5726 if (item.label == "flags.type") 5727 { 5728 item.label = "Type"; 5729 }; 5730 5731 if (item.label == "yr") 5732 { 5733 item.label = "Year"; 5734 }; 5735 5736 if (item.label == "finalPriceRange" || item.label == "FinalPriceRange") 5737 { 5738 item.label = "Price Range"; 5739 }; 5740 5741 if (item.label == "monthlyPaymentRange") 5742 { 5743 item.label = "Monthly Payment"; 5744 } 5745 5746 if (item.label == "genericColor") 5747 { 5748 item.label = "Color"; 5749 }; 5750 5751 if (item.label == "mileageRange") 5752 { 5753 item.label = distanceUnit + " Range"; 5754 }; 5755 5756 if (item.label == "vehiclehistory") 5757 { 5758 item.label = "Vehicle History"; 5759 }; 5760 if (item.label == "finalPriceInt") 5761 { 5762 item.label = "Price Range"; 5763 }; 5764 if(item.label == "transmissionType") 5765 { 5766 item.label = "Transmission"; 5767 } 5768 if (item.label == "rangeSliderPrice") 5769 { 5770 item.label = "Price"; 5771 }; 5772 5773 if (item.label == "modelCategory.lvl1") 5774 { 5775 item.label = "Model"; 5776 item.refinements = item.refinements.map((ref) => ({ ...ref, label: ref.label.split(" > ")[1]})); 5777 } 5778 }); 5779 return items; 5780 } 5781 }) 5782 ); 5783 5784 /** 5785 * Remove previous and next arrows if there's only 1 image in the stack. 5786 * Swiper has this functionality supposedly with watchOverflow: true 5787 * but it was not working when set 5788 * 5789 * @param sliderElm 5790 * @private 5791 */ 5792 function _maybeRemoveSwiperNavigation(sliderElm) { 5793 let imageCount = 0; 5794 const slides = sliderElm.querySelectorAll('.swiper-slide') 5795 5796 if (slides.length <= 1) { 5797 let navElements = sliderElm.querySelectorAll('.swiper-button-next,.swiper-button-prev') 5798 if (navElements.length) {
5799 navElements.forEach( (el) => { 5800 el.remove() 5801 }) 5802 } 5803 } 5804 } 5805 5806 /** 5807 * Limit the amount of images per vehicle card by using the SRP max images option in AG Options 5808 * 5809 * Two fixes, 2026-08-21, hunting the DOM weight behind the keystroke-lag 5810 * reports: 5811 * 5812 * 1. This used to run only when a carousel first scrolled INTO VIEW, so 5813 * every off-screen card kept its full slide stack in the DOM through 5814 * every re-render - the trim only ever helped cards the shopper had 5815 * already reached. It now also runs as part of the render rebuild 5816 * (_buildSRPImageCarousel), so excess slides leave the DOM the moment 5817 * the cards do exist, on every card, every render. Style recalculation 5818 * and layout pay per node whether or not a card is on screen (unless 5819 * content-visibility hides it, which older Safari lacks). 5820 * 5821 * 2. The gate was hard-coded "length > 5", which silently ignored a 5822 * configured cap below five. It now gates on the cap itself. 5823 * 5824 * ?da-slide-cap=N overrides the cap for one request - the way to measure 5825 * "what would a tighter cap buy" on a live dealer without touching their 5826 * setting. 5827 * 5828 * @private 5829 */ 5830 // The ?da-slide-cap=N override, read once per page instead of once per 5831 // trim call - it cannot change while the page lives. 5832 var daSlideCapOverride = parseInt(new URLSearchParams(window.location.search).get('da-slide-cap'), 10); 5833 5834 function _limitSlidesPerVehicleCard(scope) { 5835 // With a scope, trim just that carousel; without one, sweep the page. 5836 let vehicleCardCarousels = scope ? [scope] : document.querySelectorAll('.srp-swiper-vehicles'); 5837 5838 let srpMaxImageLength = 5; 5839 if (daSlideCapOverride > 0) { 5840 srpMaxImageLength = daSlideCapOverride; 5841 } 5842
5843 vehicleCardCarousels.forEach(slider => { 5844 5845 let swiperWrapper = slider.querySelector('.swiper-wrapper'); 5846 let swiperSlides = swiperWrapper.querySelectorAll('.swiper-slide'); 5847 5848 if (swiperSlides.length > srpMaxImageLength && ! swiperWrapper.dataset.maximages) { 5849 5850 for (let i = srpMaxImageLength; i < swiperSlides.length; i++) { 5851 swiperWrapper.removeChild(swiperSlides[i]); 5852 } 5853 5854 swiperWrapper.setAttribute('data-maximages', srpMaxImageLength); 5855 } 5856 }); 5857 } 5858 5859 5860 /** 5861 * Transform the incentives data to be more easily accessible in the template 5862 * 5863 * @private 5864 */ 5865 function transformIncentives(item) { 5866 5867 if (!showConditionalIncentives || !item.conditionalIncentives) return item; 5868 5869 const formatDate = (dateString) => { 5870 if (!dateString) return null; 5871 const date = new Date(dateString); 5872 const month = (date.getMonth() + 1).toString().padStart(2, '0'); 5873 const day = date.getDate().toString().padStart(2, '0'); 5874 const year = date.getFullYear(); 5875 return `${month}-${day}-${year}`; 5876 }; 5877 5878 const mapNexusIncentive = inc => { 5879 if (!inc.value || inc.value === 0) return null; 5880 5881 const incentive = {}; 5882 if (inc.title) incentive.programDescription = inc.title; 5883 if (inc.title) incentive.programName = inc.title; 5884 if (inc.value) incentive.programValue = inc.value; 5885 if (inc.disclaimer) incentive.disclaimerText = inc.disclaimer; 5886 if (inc.effectiveDate) incentive.effectiveDate = formatDate(inc.effectiveDate); 5887 if (inc.expiryDate) incentive.expiryDate = formatDate(inc.expiryDate); 5888 if (inc.description) { 5889 incentive.programRuleList = [{ 5890 description: inc.description 5891 }]; 5892 } 5893 return incentive; 5894 }; 5895 5896 if (isNexusToyota || isNexusAcura || isNexusHonda || isNexusEnabled) { 5897 item.conditionalIncentives = Array.isArray(item.conditionalIncentives) 5898 ? item.conditionalIncentives 5899 .map(mapNexusIncentive) 5900 .filter(incentive => incentive !== null && Object.keys(incentive).length > 0) 5901 : []; 5902 5903 item.incentives = Array.isArray(item.incentives) 5904 ? item.incentives 5905 .map(mapNexusIncentive) 5906 .filter(incentive => incentive !== null && Object.keys(incentive).length > 0) 5907 : []; 5908 } 5909 5910 5911 let priorityIncentives = item.conditionalIncentives.filter(incentive => { 5912 const desc = (incentive.programDescription || '').toString().toLowerCase(); 5913 return desc.includes('military') || desc.includes('college') || 5914 desc.includes('graduate') || desc.includes('first responder'); 5915 }); 5916 5917 let otherIncentives = item.conditionalIncentives.filter(incentive => { 5918 const desc = (incentive.programDescription || '').toString().toLowerCase(); 5919 return !desc.includes('military') && !desc.includes('college') && 5920 !desc.includes('graduate') && !desc.includes('first responder'); 5921 }); 5922 5923 if (priorityIncentives.length === 0) 5924 { 5925 priorityIncentives = item.conditionalIncentives.slice(0, 3); 5926 otherIncentives = otherIncentives.slice(3, otherIncentives.length); 5927 } 5928 5929 const regularIncentives = item.incentives || []; 5930 5931 const remainingIncentivesCount = otherIncentives.length + regularIncentives.length; 5932 5933 item._transformed = { 5934 priorityIncentives, 5935 otherIncentives, 5936 incentives: item.incentives || [], 5937 hasAdditionalIncentives: otherIncentives.length > 0, 5938 remainingIncentivesCount 5939 }; 5940 5941 return item; 5942 } 5943 5944 /** 5945 * Live Swiper instances and the observer that lazily creates them, kept so 5946 * the NEXT render can tear them down. 5947 * 5948 * Swiper attaches its drag-tracking listeners (touchmove, pointermove, 5949 * touchend and friends) to document, per instance - it has to, to keep 5950 * tracking a drag that leaves the container. InstantSearch replaces the 5951 * whole results list on every render, so the containers those instances 5952 * were built on are discarded, but the instances themselves - and their 5953 * document-level listeners - were never destroyed. Measured on the live 5954 * i95 SRP: ~220 document/window listeners added per six-character search 5955 * by swiper-bundle alone, none ever removed, 1,873 net after six searches. 5956 * Every tap on the page then runs the whole accumulated chain, which is 5957 * the path WebKit dispatches slowest. 5958 * 5959 * Same shape for the IntersectionObserver: a fresh one per render, 5960 * observing the new cards, with the old one left alive holding the old 5961 * ones. destroy() + disconnect() at the top of the rebuild is the whole 5962 * fix. Not behind a Theme Options switch for the same reason the delegated 5963 * click handlers were not: removing a leak has no behaviour to opt out of. 5964 */ 5965 var daSwipers = []; 5966 var daSwiperObserver = null; 5967 5968 /** 5969 * Builds the SRP vehicle image carousel on the vehicle card 5970 * 5971 * @private 5972 */ 5973 function _buildSRPImageCarousel() { 5974 // Tear down the previous render's carousels before building this one.
5975 // cleanStyles stays false: the old containers are already detached, 5976 // so restyling them is wasted work. 5977 daSwipers.forEach(function (s) { 5978 try { s.destroy(true, false); } catch (e) { /* already dead is fine */ } 5979 }); 5980 daSwipers.length = 0; 5981 5982 if (daSwiperObserver) { 5983 daSwiperObserver.disconnect(); 5984 } 5985 5986 // Trim excess slides from EVERY card now, not on first intersection - 5987 // see the note on _limitSlidesPerVehicleCard. The in-intersect call 5988 // below stays as a belt for slides added late by anything else. 5989 _limitSlidesPerVehicleCard(); 5990 5991 /** 5992 * b/o: Allow the loading of Swipers when needed and scrolled into view 5993 * using the javascript intersection Observer API 5994 */ 5995 const observerOptions = { 5996 root: null, 5997 rootMargin: '0px', 5998 threshold: 0.2 // when 20% of the element is in view proceed with loading the swiper 5999 }; 6000 6001 function handleIntersect(entries, observer) { 6002 entries.forEach(entry => { 6003 if (entry.isIntersecting) { 6004 // Belt for slides added late by anything else, scoped to 6005 // the one carousel entering view - the unscoped call here 6006 // re-walked every wrapper on the page per intersecting 6007 // card, ~576 wrapper scans across one scrolled 24-card 6008 // page, all duplicating the render-time trim above. 6009 _limitSlidesPerVehicleCard(entry.target); 6010 _maybeRemoveSwiperNavigation(entry.target) 6011 // Initialize Swiper for this container 6012 daSwipers.push(new Swiper(entry.target, { 6013 loop: true, 6014 /** 6015 * Swiper's default touchAngle is 45 degrees, meaning it claims 6016 * any drag within 45 degrees of horizontal as a carousel swipe. 6017 * A thumb flick is rarely perfectly vertical, so on a phone - 6018 * where these cards fill most of the screen - a large share of 6019 * scroll attempts get swallowed by the carousel and the page 6020 * does not move. That reads exactly as "scrolling is stuck". 6021 * 6022 * 25 degrees keeps deliberate horizontal swipes working while 6023 * letting anything steeper scroll the page. 6024 */ 6025 touchAngle: 25, 6026 navigation: { 6027 nextEl: `.swiper-button-next`, 6028 prevEl: `.swiper-button-prev` 6029 } 6030 })); 6031 6032 observer.unobserve(entry.target); 6033 } 6034 }); 6035 } 6036 6037 daSwiperObserver = new IntersectionObserver(handleIntersect, observerOptions); 6038 // Get all of the swipers on the page 6039 let vehicleCardCarousels = document.querySelectorAll('.srp-swiper-vehicles'); 6040
6041 vehicleCardCarousels.forEach(slider => { 6042 daSwiperObserver.observe(slider); 6043 }); 6044 } 6045 6046 /* b/o: Image Aspect Ratio Fix */ 6047 6048 /** 6049 * Calculate a new height based on previous values as well as a new width 6050 * 6051 * @param newWidth the new width of the element to calulcate the height 6052 * @param originalWidth the original width of the item to find aspect ratio 6053 * @param originalHeight the original height of the item to find aspect ratio 6054 * @returns number 6055 */ 6056 function calculateHeight(newWidth, originalWidth, originalHeight) { 6057 const aspectRatio = originalWidth / originalHeight; 6058 const newHeight = newWidth / aspectRatio; 6059 return parseFloat(newHeight.toFixed(1)); 6060 } 6061 6062 /* 6063 * e/o: Image Aspect Ratio Fix 6064 * 6065 * _debounce/_onResize/_constrainImageAspectRatio were removed here. The 6066 * resize handler measured every card with jQuery .width() and then did 6067 * nothing with the result - the two lines that used it had been commented 6068 * out - so all it did was force a synchronous layout per vehicle card on 6069 * every render. It was also called from onRenderHandler, and each call 6070 * added another window resize listener that was never removed. 6071 * 6072 * It was the single largest remaining cost on this page: 2,863ms of forced 6073 * reflow attributed to jQuery's dimension getter while typing one search. 6074 * 6075 * Note: shortcodes/inventory-widget/sc.inventory-widget.php still carries a 6076 * copy of the same dead pattern. 6077 */ 6078 6079 /** 6080 * Render is deliberately split in two. 6081 * 6082 * instantsearch re-renders roughly 1.7 times per keystroke - measured at ten 6083 * renders for six typed characters on the used-vehicles SRP. The tail of this 6084 * handler re-initialises against the freshly built card DOM: Swiper carousels, 6085 * lazy-image observers, SmartPath, and the forms. None of that is incremental 6086 * state - every one rebuilds from the current result set - so running them on 6087 * an intermediate render produces work the next keystroke immediately throws 6088 * away. 6089 * 6090 * onRenderImmediate() is everything that keeps what is on screen truthful: 6091 * result counts, facet container visibility, filter tags. Delaying any of it 6092 * would leave stale numbers on screen while the user types. 6093 * 6094 * onRenderSettled() is everything that re-initialises, trailing-debounced so 6095 * it runs once when typing stops. 250ms rather than the 100ms used for the 6096 * search debounce above, because this work is an order of magnitude heavier 6097 * and none of it is visible state. 6098 * 6099 * Gated on Theme Options -> Performance -> "Defer post-render work on the SRP", 6100 * on by default, with the settle delay configurable there too. 6101 * ?da-render-split=off still runs both halves inline for this request only, so 6102 * support can rule it in or out on a live page without changing the setting. 6103 */ 6104 // Floor 100, matching the spinner: its old min of 0 made daTypingActive() 6105 // always false, which switched render-on-settle off while its switch still 6106 // read on. Below about 100ms neither feature does anything useful anyway. 6107 var DA_SETTLE_MS = 250; 6108 var daSettleTimer = null; 6109 var daRenderSplit = true && new URLSearchParams(window.location.search).get('da-render-split') !== 'off'; 6110 6111 function onRenderHandler() 6112 { 6113 /** 6114 * Cleared before the mid-burst return on purpose: a timer armed by 6115 * the last pre-burst render would otherwise fire DURING the typing 6116 * window the gate below exists to protect - full Swiper rebuild, 6117 * slide trims, a burned reaper generation, all for a render that 6118 * never happened. The settled render that follows the held response 6119 * re-arms it, so nothing is lost by clearing here. 6120 */ 6121 clearTimeout(daSettleTimer); 6122 6123 /** 6124 * Mid-burst, this render can only be loading-state churn: responses 6125 * are being held by the render-on-settle gate, so nothing on screen 6126 * has changed and both halves would run for nothing - measured at 6127 * ~4.7s of main-thread time across one fast-typed word on the 6128 * 4x-throttled bench, all of it between keystrokes the user was 6129 * still typing. The render that matters fires when the held response 6130 * delivers at settle, and typing is quiet by definition then, so 6131 * this guard is never true for it. 6132 */ 6133 if (daRenderOnSettle && daTypingActive()) 6134 { 6135 return; 6136 } 6137 6138 onRenderImmediate(); 6139 6140 if (!daRenderSplit) 6141 { 6142 onRenderSettled(); 6143 return; 6144 } 6145 6146 daSettleTimer = setTimeout(onRenderSettled, DA_SETTLE_MS); 6147 } 6148 6149 function onRenderImmediate() 6150 { 6151 // Update smartpath disclaimer 6152 SmartPathDisclaimer("Sale Pending", ".dv-sp-disclaimer"); 6153 6154 /** 6155 * If no card is in the view, and we are not on mobile, scroll to top. 6156 * 6157 * Delegated off document and namespaced, because onRenderHandler runs on 6158 * every render: the previous .click() bound a fresh handler to every 6159 * refinement label each time, so after N searches a single click ran N 6160 * copies - N viewport measurements and N scroll animations. Binding once 6161 * by delegation also survives the labels being replaced on re-render. 6162 */ 6163 var mobile = window.matchMedia("(max-width: 1024px)"); 6164 $(document) 6165 .off("click.daSrpScrollTop") 6166 .on("click.daSrpScrollTop", ".ais-RefinementList-label", function() { 6167 if (!$('.listing-container').isInViewport() && !mobile.matches) 6168 { 6169 $("html,body").animate({scrollTop:$(".result-wrapper").offset().top - 200},"1000"); 6170 } 6171 }); 6172 6173 // Lazy-image observers and the card carousels are built in 6174 // onRenderSettled() - see the note on the split above. 6175 6176 /** 6177 * Filter panel visibility, by class rather than jQuery show()/hide(). 6178 * 6179 * jQuery hide() is cheap - it just writes display:none - but show() has to 6180 * work out the element's default display, which means getComputedStyle 6181 * against a DOM the render has just dirtied. That is a forced synchronous 6182 * layout per call, and there are twenty calls here. Measured at 686ms for 6183 * 34 elements while typing a single search; hide() over the same run cost
6184 * 1ms. Toggling a class invalidates style without forcing a read. 6185 * 6186 * Equivalent because none of these containers is hidden by a stylesheet - 6187 * every one resolves to display:block from CSS alone, in the parent theme 6188 * and in every child theme - so removing the class lands them exactly 6189 * where show() would have. 6190 */ 6191 var daShow = function (sel) { $(sel).removeClass("da-srp-hidden"); }; 6192 var daHide = function (sel) { $(sel).addClass("da-srp-hidden"); }; 6193 6194 //If a filter list does not have no items in it, be sure it is shown 6195 $(".ais-RefinementList").not(".ais-RefinementList--noRefinement").each(function () { 6196 daShow($(this).parents().eq(1)); 6197 }); 6198 6199 //Hide any filter list that has no items in it 6200 $(".ais-RefinementList--noRefinement").each(function () { 6201 daHide($(this).parents().eq(1)); 6202 }); 6203 6204 if ($("#status-list > div > ul").children().length == 1) 6205 { 6206 daHide(".status-container"); 6207 } 6208 else 6209 { 6210 daShow(".status-container"); 6211 } 6212 6213 if ($("#engine-list > div > ul").children().length == 1) 6214 { 6215 daHide(".engine-container"); 6216 } 6217 else 6218 { 6219 daShow(".engine-container"); 6220 } 6221 6222 //If a make is selected, show the model filter list. 6223 if ($("#make-list ul li").hasClass("ais-RefinementList-item--selected")) 6224 { 6225 daShow(".model-container"); 6226 } 6227 else if ($("#make-list ul li").length > 1) 6228 { 6229 //If a make is not selected, and there is more than one make in the list, hide the model list 6230 daHide(".model-container"); 6231 } 6232 else 6233 { 6234 //Only one make is in the list, so keep model list showing, and hide the make list. 6235 daHide(".make-container"); 6236 } 6237 6238 //If a model is selected, show the trim filter list. 6239 if ($("#model-list ul li").hasClass("ais-RefinementList-item--selected") || $("#modelCategory-list ul li").hasClass("ais-RefinementList-item--selected")) 6240 { 6241 daShow(".trim-container"); 6242 } 6243 else 6244 { 6245 // 6246 daHide(".trim-container"); 6247 } 6248 6249 //If a truck is selected, show the cab/bed filter list. 6250 var child = $(".srp-Truck"); 6251 6252 if ($(child).parent().parent().parent().hasClass("ais-RefinementList-item--selected")) 6253 { 6254 daShow(".bed-container, .cab-container"); 6255 } 6256 else{ 6257 daHide(".bed-container, .cab-container"); 6258 } 6259 6260 //Show bed and cab info if Model name of truck is selected 6261 if($("#body-list div > ul").find("li").length === 1){ 6262 if ($(child).parent().parent().parent().hasClass("ais-RefinementList-item")) 6263 { 6264 daShow(".bed-container, .cab-container"); 6265 } 6266 else{ 6267 daHide(".bed-container, .cab-container"); 6268 } 6269 } 6270 6271 if ($(".fuel-container input[value='Electric']").is(":checked")) 6272 { 6273 $(".range.container").show(); 6274 } 6275 else 6276 { 6277 $(".range-container").hide(); 6278 } 6279 6280 /** 6281 * Change mobile filter bar color when a filter is selected. 6282 * 6283 * Delegated and namespaced for the same reason as the scroll-top handler 6284 * above: .click() bound a fresh handler on every render, so after N renders 6285 * one tap ran N copies. Typing six characters is ten renders. 6286 */ 6287 $(document) 6288 .off("click.daSrpFilterBar") 6289 .on("click.daSrpFilterBar", ".ais-RefinementList-item", function () { 6290 $('.showFiltersNonLegacy').css('background-color', '#000000'); 6291 $('.showFiltersNonLegacy').css('color', '#FFFFFF'); 6292 }); 6293 6294 //Results X of X Text 6295 if(parseInt($("#numberHits").text().replace(/,/g,''), 10) < 24) 6296 { 6297 $('#hitsPage').text($("#numberHits").text()); 6298 } 6299 else if (parseInt($('.ais-Pagination-item--selected > .ais-Pagination-link').attr('aria-label'), 10) > 1) 6300 { 6301 var page = parseInt($('.ais-Pagination-item--selected > .ais-Pagination-link').attr('aria-label'), 10); 6302 var hits = 24 * (page - 1); 6303 $('#hitsStart').text(hits); 6304 var hitsOnPage = parseInt($('#numberHits').text().replace(/,/g,''), 10); 6305 if ((hitsOnPage - (hits)) < 24) 6306 { 6307 $('#hitsPage').text(hitsOnPage); 6308 } 6309 else 6310 { 6311 $('#hitsPage').text((hits) + 24); 6312 } 6313 } 6314 else 6315 { 6316 $("#hitsStart").text(1); 6317 $("#hitsPage").text(24); 6318 } 6319 6320 6321 //Deselection of facets based on hierarchy - delegated, same reasoning as above. 6322 $(document) 6323 .off("click.daSrpFacetHierarchy")
6324 .on("click.daSrpFacetHierarchy", "#make-list ul li, #trim-list ul li, #model-list ul li", function () { 6325 if ($(this).hasClass("ais-RefinementList-item--selected")) { 6326 userInteractedWithFacets = true; 6327 checkAndRemoveFacets(); 6328 } 6329 }); 6330 6331 // $(".srp-integrations-video").click(function() { 6332 // showVideo(event, $(this).attr('data-video-url')); 6333 // }); 6334 6335 //Hide filter tags if there are no current selected filters 6336 if ($("#filterTags .ais-CurrentRefinements-list").has('li').length == 0) 6337 { 6338 $("#filterTags").hide(); 6339 $(".dv-srp-filter-clear-btn").hide(); 6340 $(".dv-srp-filter-tags").hide(); 6341 } 6342 else 6343 { 6344 $("#filterTags").show(); 6345 $(".dv-srp-filter-clear-btn").css('display', 'inline-flex'); 6346 $(".dv-srp-filter-tags").show(); 6347 } 6348 6349 } 6350 6351 /** 6352 * Watch an image for the moment it can first paint. 6353 * 6354 * <img> exposes only load and error, and both fire when the LAST byte arrives. 6355 * naturalWidth, by contrast, becomes non-zero as soon as the browser has parsed 6356 * the image header - well before the download finishes, and the point from which 6357 * it has both dimensions and pixels to draw. That is the closest thing the 6358 * platform gives us to a "started rendering" signal. 6359 * 6360 * It is also exactly when the CSS placeholder box stops being needed: until 6361 * naturalWidth is known the image cannot size itself, and after it can. So the 6362 * same signal clears the spinner and releases the reserved box. 6363 * 6364 * One shared rAF loop rather than a timer per image: a 24-card page has ~120 6365 * images in flight, and this is one callback per frame instead of 120. 6366 */ 6367 var daPainting = []; 6368 var daPaintRaf = null; 6369 6370 function daPaintTick() 6371 { 6372 for (var i = daPainting.length - 1; i >= 0; i--) 6373 { 6374 var watch = daPainting[i]; 6375 6376 if (!watch.img.isConnected || watch.img.naturalWidth > 0) 6377 { 6378 daPainting.splice(i, 1); 6379 watch.done(); 6380 } 6381 } 6382 6383 daPaintRaf = daPainting.length ? requestAnimationFrame(daPaintTick) : null; 6384 } 6385 6386 function daWatchFirstPaint(img, done) 6387 { 6388 daPainting.push({ img: img, done: done }); 6389 6390 if (daPaintRaf === null) 6391 { 6392 daPaintRaf = requestAnimationFrame(daPaintTick); 6393 } 6394 } 6395 6396 /** 6397 * Trailing-debounced half of the render. 6398 * 6399 * Everything here re-initialises against the freshly rendered cards and 6400 * rebuilds from the current result set, so running it once after typing stops 6401 * is equivalent to running it on every intermediate render - minus the work 6402 * that was being discarded. Anything added here must be idempotent. 6403 */ 6404 function onRenderSettled() 6405 { 6406 /** 6407 * A settled render is a listener generation boundary. 6408 * 6409 * The reaper (template/partials/observer-governor.php, on by default) 6410 * tracks document-level listeners bound by vendors that re-decorate the 6411 * cards on every render and never unbind - dg-inline-save-heart being 6412 * the measured one. Telling it a render settled lets it retire the 6413 * batches serving cards that no longer exist. No-op when the partial 6414 * did not emit the reaper. 6415 */ 6416 if (window.DAListenerReaper) 6417 { 6418 window.DAListenerReaper.advance(); 6419 } 6420 6421 //Image lazy loading 6422 var lazyImages = [].slice.call(document.querySelectorAll("img.lazy")); 6423 if ("IntersectionObserver" in window) 6424 { 6425 let lazyImageObserver = new IntersectionObserver(function (entires, observer) { 6426 entires.forEach(function (entry) { 6427 if (entry.isIntersecting) 6428 { 6429 let lazyImage = entry.target; 6430 6431 /** 6432 * Clear the Swiper preloader once the image resolves. 6433 * 6434 * Bound BEFORE src is assigned: a cached image can fire load 6435 * synchronously on assignment, and a listener attached after 6436 * that would never run - leaving the spinner going forever. 6437 * 6438 * Error is handled too. A dead image URL should show the 6439 * browser's own broken state rather than spin indefinitely, 6440 * which at least reads as 'failed' instead of 'still trying'. 6441 */ 6442 let clearPreloader = function () { 6443 let slide = lazyImage.parentElement; 6444 let preloader = slide && slide.querySelector(".swiper-lazy-preloader"); 6445 6446 if (preloader) 6447 { 6448 preloader.remove(); 6449 } 6450 6451 lazyImage.classList.remove("da-img-loading"); 6452 }; 6453 6454 lazyImage.addEventListener("load", clearPreloader, { once: true }); 6455 lazyImage.addEventListener("error", clearPreloader, { once: true }); 6456 6457 lazyImage.src = lazyImage.dataset.src; 6458 6459 /** 6460 * Hand the reserved box from .lazy to .da-img-loading rather 6461 * than dropping it here. 6462 * 6463 * Removing .lazy on its own released the placeholder box the 6464 * instant src was assigned - before a single byte had arrived, 6465 * so the image still had no intrinsic size and the slide 6466 * collapsed back to its 16px alt-text line box. The spinner 6467 * centres on the slide, so it visibly jumped to the top and 6468 * then returned once the photo landed. 6469 * 6470 * .da-img-loading keeps the box but not the visibility:hidden, 6471 * so a progressive image paints as it arrives instead of 6472 * appearing all at once at the end. 6473 */ 6474 lazyImage.classList.remove("lazy"); 6475 lazyImage.classList.add("da-img-loading"); 6476 6477 daWatchFirstPaint(lazyImage, clearPreloader); 6478 6479 lazyImageObserver.unobserve(lazyImage); 6480 } 6481 }); 6482 }); 6483
6484 lazyImages.forEach(function (lazyImage) { 6485 lazyImageObserver.observe(lazyImage); 6486 }); 6487 } 6488 6489 // Initialize vehicle images carousel 6490 _buildSRPImageCarousel(); 6491 6492 6493 //Disable then reenabled the forms. 6494 disableForms(); 6495 6496 initForms(); 6497 6498 6499 //SD Analytics 6500 if (haveSdAnalytics && typeof(sd) !== "undefined") 6501 { 6502 var numberHits = $("#numberHits").text(); 6503 6504 if (numberHits === '0' || numberHits === "") { 6505 6506 if (sdInitialFilterSearchSent) { 6507 sd('dataLayer', { 6508 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 6509 displayType: 'modal', 6510 events: 'formShown' 6511 }); 6512 sd('send'); 6513 } else { 6514 sdFormShownPending = true; 6515 } 6516 6517 /** 6518 * Delegated and namespaced so re-running this branch replaces the 6519 * handler instead of stacking another one. See sdFormInitHandled 6520 * at the top of the file for what the stacking actually cost. 6521 * 6522 * Bound off document rather than the wrapper because the form markup 6523 * is replaced when the modal is rebuilt, which would strip a handler 6524 * bound directly to the inputs. 6525 */ 6526 sdFormInitHandled = false; 6527 6528 $(document) 6529 .off("click.daSrpSdFormInit") 6530 .on("click.daSrpSdFormInit", ".gform_wrapper input", function () { 6531 if (sdFormInitHandled) 6532 { 6533 return; 6534 } 6535 6536 sendShiftDigitalFormEvent({ 6537 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 6538 displayType: 'modal', 6539 eventName: 'formInitiation' 6540 }); 6541 6542 sdFormInitHandled = true; 6543 }); 6544 6545 $(document) 6546 .off("input.daSrpSdField change.daSrpSdField") 6547 .on("input.daSrpSdField change.daSrpSdField", ".gform_wrapper input, .gform_wrapper textarea, .gform_wrapper select", function () { 6548 if (shouldTrackShiftDigitalFieldInteraction(this)) 6549 { 6550 sendShiftDigitalFormEvent({ 6551 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 6552 displayType: 'modal', 6553 eventName: 'formFieldInteraction', 6554 fieldTarget: this 6555 }); 6556 } 6557 }); 6558 } 6559 6560 } 6561 } 6562 6563 /** 6564 * Convert old 'model' query parameters to new 'modelCategory.lvl1' hierarchical refinements 6565 * on the first render if the new filter is enabled but the old one is disabled. 6566 * 6567 * This ensures legacy menu items (e.g., ?model=Corolla) still work by mapping them 6568 * to the new grouped/nested format (e.g., Corolla > Corolla). 6569 */ 6570 let modelCategoryConverted = false; 6571 search.on('render', () => { 6572 // Only run once and only when helper/results are ready 6573 if (modelCategoryConverted || !search.helper || !search.helper.lastResults) return; 6574 6575 // 1. Detect model parameters in the URL 6576 const urlParams = new URLSearchParams(window.location.search); 6577 const modelsFromUrl = urlParams.getAll('model'); 6578 6579 // Only proceed if 'model' exists but 'modelCategory.lvl1' isn't refined yet 6580 if (modelsFromUrl.length > 0 && !urlParams.has('modelCategory.lvl1')) { 6581 // 2. Fetch all available hierarchical model categories from current search results 6582 const allFacetValues = search.helper.lastResults.getFacetValues('modelCategory.lvl1'); 6583 6584 if (allFacetValues && allFacetValues.length > 0) { 6585 const matchedParents = new Set(); 6586 6587 // 3. Find matches for each model in the URL 6588 modelsFromUrl.forEach(model => { 6589 const matchedItem = allFacetValues.find(item => { 6590 const parts = item.name.split(' > '); 6591 const parent = parts[0]; 6592 const child = parts[1] || parts[0]; 6593 // Match against child (Corolla) OR parent (Highlander) 6594 return child.toLowerCase() === model.toLowerCase() || parent.toLowerCase() === model.toLowerCase(); 6595 }); 6596 6597 if (matchedItem) { 6598 // Collect the parent group name (e.g., 'Highlander' for 'Grand Highlander') 6599 matchedParents.add(matchedItem.name.split(' > ')[0]); 6600 } 6601 }); 6602 6603 if (matchedParents.size > 0) { 6604 const matches = []; 6605 6606 // 4. Find ALL sub-categories belonging to the matched parent groups
6607 allFacetValues.forEach(item => { 6608 const parent = item.name.split(' > ')[0]; 6609 if (matchedParents.has(parent)) { 6610 matches.push(item.name); 6611 } 6612 }); 6613 6614 if (matches.length > 0) { 6615 modelCategoryConverted = true; 6616 6617 // 5. Apply the new refinements and trigger a fresh search 6618 matches.forEach(m => search.helper.addDisjunctiveFacetRefinement('modelCategory.lvl1', m)); 6619 search.helper.search(); 6620 6621 // Note: InstantSearch routing will automatically clean up the URL to the new format 6622 } 6623 } 6624 } 6625 } 6626 }); 6627 6628search.on('render', onRenderHandler); 6629search.on('render', handleSdSrpRenderAnalytics); 6630 6631/** 6632 * Tell governed third parties a render happened, rather than leaving them to 6633 * infer it from thousands of mutation records. See 6634 * template/partials/observer-governor.php - a no-op if that is not loaded. 6635 * 6636 * Second argument stays false: the sentinel wakes anything that rescans the DOM 6637 * on its own, which covers the vendors currently governed. Only pass true for a 6638 * vendor that reads addedNodes to find new content, and verify it there first. 6639 */ 6640search.on('render', function () { 6641 if (window.DAObserverGovernor) { 6642 window.DAObserverGovernor.notify('#srp-results', false); 6643 } 6644}); 6645 6646search.on('render', (() => { 6647 let timer; 6648 return () => { 6649 clearTimeout(timer); 6650 timer = setTimeout(() => { 6651 document.dispatchEvent(new CustomEvent('srp:renderStart')); 6652 // give time for the instantsearch lib to render 6653 requestAnimationFrame(() => { 6654 document.dispatchEvent(new CustomEvent('srp:renderComplete')); 6655 }); 6656 }, 200); 6657 }; 6658})()); 6659 6660searchClient.search([{indexName: indexName, params: {query: '', hitsPerPage: 0, facets: ['exteriorHex']}}]) 6661 .then(function(res) { 6662 var colorAttr = (res.results[0].facets && res.results[0].facets['exteriorHex']) ? 'exteriorHex' : 'genericColor'; 6663 search.addWidget(instantsearch.widgets.refinementList({ 6664 container: '#color-list', 6665 attribute: colorAttr, 6666 operator: 'or', 6667 // Swatches opt out of daFacetLimit - a Show more button would land 6668 // inside the flex grid - but still need a limit over the default 10. 6669 limit: 100000, 6670 templates: { item: "<i style=\"background: {{value}};\" class=far fa-check\"></i>" } 6671 })); 6672 search.start(); 6673 }) 6674 .catch(function() { 6675 search.addWidget(instantsearch.widgets.refinementList({ 6676 container: '#color-list', 6677 attribute: 'genericColor', 6678 operator: 'or', 6679 limit: 100000, 6680 templates: { item: "<i style=\"background: {{value}};\" class=far fa-check\"></i>" } 6681 })); 6682 search.start(); 6683 }); 6684 6685/** 6686 * Mobile keyboard affordances for the search box. 6687 * 6688 * InstantSearch renders the field itself, so these are applied after start(). 6689 * Two problems on a phone: the Return key had no clear meaning, and once the 6690 * keyboard was up there was no obvious way down - the field sits near the top 6691 * of the page with no surrounding tappable dead space. 6692 * 6693 * - enterkeyhint labels the Return key "Search" on iOS and Android. 6694 * - Submitting blurs, so Return actually closes the keyboard. InstantSearch 6695 * already suppresses the form's default submit, so nothing navigates. 6696 * - Scrolling the results blurs too. This is the usual mobile search pattern: 6697 * once you scroll, you are reading results rather than typing. Gated on a 6698 * real scroll distance so a stray pixel of movement does not dismiss it, 6699 * and on touch input so desktop is unaffected. 6700 */ 6701function daSetupSearchBoxKeyboard() { 6702 var searchInput = document.querySelector('#searchbox .ais-SearchBox-input'); 6703 6704 // Depending on the branch above, start() happens inside a promise, so the 6705 // field may not exist yet. Bound off 'render' and guarded, rather than run 6706 // inline - an earlier inline version silently did nothing for exactly this 6707 // reason, and looked like it worked because InstantSearch blurs on submit 6708 // by itself. 6709 if (!searchInput || searchInput.dataset.daKeyboardReady) { 6710 return; 6711 } 6712 6713 searchInput.dataset.daKeyboardReady = '1'; 6714 searchInput.setAttribute('enterkeyhint', 'search'); 6715 6716 if (window.matchMedia('(hover: none)').matches) { 6717 // Anchor on focus, not on the first scroll event. Anchoring on the first 6718 // event measures the delta from wherever that event already landed, which 6719 // is zero for anything but a slow drag. 6720 var scrollAnchor = null; 6721 6722 /** 6723 * Only a scroll the user actually drove should dismiss the keyboard. 6724 * 6725 * The first version of this compared scroll distance alone, which broke 6726 * tapping the field on iOS whenever the page was scrolled even slightly. 6727 * Focusing an input on iOS makes the BROWSER scroll: the keyboard shrinks 6728 * the visual viewport, and a collapsed address bar expands. Both move 6729 * window.scrollY well past this threshold within a frame or two of focus, 6730 * so the handler blurred the field the moment it was tapped. It worked at 6731 * the very top of the page only because there was nothing to adjust. 6732 * 6733 * A drag produces touchmove. Browser-driven scroll does not, so requiring 6734 * a recent touchmove separates the two. Anything else re-anchors instead
6735 * of dismissing, which also covers the keyboard opening mid-session. 6736 */ 6737 var lastTouchMove = 0; 6738 6739 document.addEventListener('touchmove', function () { 6740 lastTouchMove = Date.now(); 6741 }, { passive: true }); 6742 6743 searchInput.addEventListener('focus', function () { 6744 scrollAnchor = window.scrollY; 6745 }); 6746 6747 searchInput.addEventListener('blur', function () { 6748 scrollAnchor = null; 6749 }); 6750 6751 // Keyboard show/hide relays out the page. Re-anchor rather than reading it 6752 // as the shopper scrolling away from the field. 6753 if (window.visualViewport) { 6754 window.visualViewport.addEventListener('resize', function () { 6755 if (scrollAnchor !== null) { 6756 scrollAnchor = window.scrollY; 6757 } 6758 }); 6759 } 6760 6761 window.addEventListener('scroll', function () { 6762 if (scrollAnchor === null || document.activeElement !== searchInput) { 6763 return; 6764 } 6765 6766 if (Date.now() - lastTouchMove > 500) { 6767 scrollAnchor = window.scrollY; 6768 return; 6769 } 6770 6771 if (Math.abs(window.scrollY - scrollAnchor) > 40) { 6772 searchInput.blur(); 6773 } 6774 }, { passive: true }); 6775 } 6776} 6777 6778search.on('render', daSetupSearchBoxKeyboard); 6779daSetupSearchBoxKeyboard(); 6780 6781$.fn.isInViewport = function() { 6782 var elementTop = $(this).offset().top; 6783 var elementBottom = elementTop + $(this).outerHeight(); 6784 6785 var viewportTop = $(window).scrollTop(); 6786 var viewportBottom = viewportTop + $(window).height(); 6787 6788 return elementBottom > viewportTop && elementTop < viewportBottom; 6789}; 6790 6791/** 6792 * Reads the current InstantSearch helper state for the supported Shift Digital 6793 * filterSearch fields and returns a pipe-delimited value string. 6794 * 6795 * We intentionally read from the live helper refinements instead of the URL 6796 * because the router can lag one render behind on select/deselect interactions. 6797 * 6798 * @param {object} state 6799 * @param {string[]} keys 6800 * @returns {string} 6801 */ 6802function getSdStateFilterValues(state, keys) { 6803 var refinementSources = [ 6804 state.disjunctiveFacetsRefinements || {}, 6805 state.facetsRefinements || {}, 6806 state.hierarchicalFacetsRefinements || {} 6807 ]; 6808 6809 for (var sourceIndex = 0; sourceIndex < refinementSources.length; sourceIndex++) { 6810 var source = refinementSources[sourceIndex]; 6811 6812 for (var keyIndex = 0; keyIndex < keys.length; keyIndex++) { 6813 var key = keys[keyIndex]; 6814 var values = source[key]; 6815 6816 if (!values) { 6817 continue; 6818 } 6819 6820 if (!Array.isArray(values)) { 6821 values = [values]; 6822 } 6823 6824 values = values.filter(Boolean); 6825 6826 if (values.length > 0) { 6827 return values.join("|"); 6828 } 6829 } 6830 } 6831 6832 return "All"; 6833} 6834 6835/** 6836 * Reads a numeric range slider value from the InstantSearch helper state, 6837 * falling back to the facet stats (full inventory bounds) when the user 6838 * has not moved the slider. 6839 * 6840 * @param {object} helperState search.helper.state 6841 * @param {string} attribute The Algolia attribute name (e.g. 'rangeSliderPrice', 'yr') 6842 * @param {function|null} formatter Optional formatter for min/max values 6843 * @returns {string} 6844 */ 6845function getSdNumericRangeValue(helperState, attribute, formatter) { 6846 var refinements = (helperState.numericRefinements || {})[attribute] || {}; 6847 var stats = {}; 6848 6849 if (search.helper && search.helper.lastResults && search.helper.lastResults.disjunctiveFacets) { 6850 var facet = search.helper.lastResults.disjunctiveFacets.find(function(f) { return f.name === attribute; }); 6851 if (facet && facet.stats) { 6852 stats = facet.stats; 6853 } 6854 } 6855 6856 var min = refinements[">="] ? refinements[">="][0] : (stats.min != null ? stats.min : null); 6857 var max = refinements["<="] ? refinements["<="][0] : (stats.max != null ? stats.max : null); 6858 6859 if (min === null && max === null) { 6860 return "All"; 6861 } 6862 6863 if (formatter) { 6864 return formatter(min) + " - " + formatter(max); 6865 } 6866 6867 return min + " - " + max; 6868} 6869 6870/** 6871 * Returns the year for the Shift Digital filterSearch payload. 6872 * 6873 * Shift Digital wants a single year only when the shopper has actually narrowed 6874 * to one. Every "more than one year is showing" case reports "All" - including a 6875 * year slider spanning a range, which previously reported a shared "2015 - 2026" 6876 * string that read as two values in one prop. 6877 * 6878 * @param {object} helperState search.helper.state 6879 * @returns {string} 6880 */ 6881function getSdYearValue(helperState) { 6882 var yearFacetSelection = getSdStateFilterValues(helperState, ["year", "yr"]); 6883 6884 if (yearFacetSelection !== "All") { 6885 return yearFacetSelection.indexOf("|") === -1 ? yearFacetSelection : "All"; 6886 } 6887 6888 // Only a slider collapsed onto one year counts as picking a year. 6889 var sliderRefinements = (helperState.numericRefinements || {})["yr"] || {}; 6890 var min = sliderRefinements[">="] ? sliderRefinements[">="][0] : null; 6891 var max = sliderRefinements["<="] ? sliderRefinements["<="][0] : null; 6892 6893 if (min !== null && max !== null && Number(min) === Number(max)) { 6894 return String(Math.round(min)); 6895 } 6896 6897 return "All"; 6898} 6899 6900/** 6901 * Returns the min and max price as plain integers for the Shift Digital 6902 * filterSearch payload. Checks finalPriceRange bucket selections first, 6903 * then falls back to the rangeSliderPrice numeric refinements, then to 6904 * the full facet stats (inventory bounds) when no filter is active. 6905 * 6906 * @returns {{min: number|null, max: number|null}} 6907 */ 6908function getSdPriceBounds(helperState) { 6909 var refinementSources = [ 6910 helperState.disjunctiveFacetsRefinements || {}, 6911 helperState.facetsRefinements || {} 6912 ]; 6913 6914 for (var i = 0; i < refinementSources.length; i++) { 6915 var buckets = refinementSources[i]["finalPriceRange"]; 6916 if (buckets && buckets.length > 0) { 6917 var vals = Array.isArray(buckets) ? buckets : [buckets]; 6918 var mins = []; 6919 var maxes = []; 6920
6921 vals.forEach(function(bucket) { 6922 var s = bucket.replace(/[$,]/g, ''); 6923 var below = s.match(/^(\d+)\s+and\s+Below$/i); 6924 var above = s.match(/^(\d+)\s+and\s+Up$/i); 6925 var range = s.match(/^(\d+)\s+-\s+(\d+)$/); 6926 6927 if (below) { mins.push(0); maxes.push(parseInt(below[1], 10)); } 6928 else if (above) { mins.push(parseInt(above[1], 10)); } 6929 else if (range) { mins.push(parseInt(range[1], 10)); maxes.push(parseInt(range[2], 10)); } 6930 }); 6931 6932 if (mins.length > 0 || maxes.length > 0) { 6933 return { 6934 min: mins.length > 0 ? Math.min.apply(null, mins) : null, 6935 max: maxes.length > 0 ? Math.max.apply(null, maxes) : null 6936 }; 6937 } 6938 } 6939 } 6940 6941 var sliderRefinements = (helperState.numericRefinements || {})["rangeSliderPrice"] || {}; 6942 var stats = {}; 6943 6944 if (search.helper && search.helper.lastResults && search.helper.lastResults.disjunctiveFacets) { 6945 var priceFacet = search.helper.lastResults.disjunctiveFacets.find(function(f) { 6946 return f.name === "rangeSliderPrice"; 6947 }); 6948 if (priceFacet && priceFacet.stats) { 6949 stats = priceFacet.stats; 6950 } 6951 } 6952 6953 var min = sliderRefinements[">="] ? sliderRefinements[">="][0] : (stats.min != null ? stats.min : null); 6954 var max = sliderRefinements["<="] ? sliderRefinements["<="][0] : (stats.max != null ? stats.max : null); 6955 6956 return { 6957 min: min !== null ? Math.round(min) : null, 6958 max: max !== null ? Math.round(max) : null 6959 }; 6960} 6961 6962/** 6963 * Builds the Shift Digital filterSearch payload from the current InstantSearch 6964 * helper state. 6965 * 6966 * This keeps supported facet values in sync with the interaction that triggered 6967 * the render instead of relying on URL parameters that may still reflect the 6968 * previous refinement state. 6969 * 6970 * @returns {{status: string, minPrice: number|null, maxPrice: number|null, year: string, mileage: string, make: string, model: string, color: string, trim: string, bodyStyle: string, features: string, drivetrain: string}} 6971 */ 6972function buildSdFilterSearchPayload() { 6973 var helperState = search.helper && search.helper.state ? search.helper.state : {}; 6974 var status = "All"; 6975 var certificationRefinements = getSdStateFilterValues(helperState, ["flags.type"]); 6976 6977 if (certificationRefinements !== "All") { 6978 var selectedCount = certificationRefinements.split("|").length; 6979 var totalCount = 0; 6980 6981 if (search.helper && search.helper.lastResults) { 6982 var facetValues = search.helper.lastResults.getFacetValues("flags.type"); 6983 if (Array.isArray(facetValues)) { 6984 totalCount = facetValues.length; 6985 } 6986 } 6987 6988 if (totalCount > 0 && selectedCount >= totalCount) { 6989 status = "Mixed"; 6990 } else { 6991 status = "CPO"; 6992 } 6993 } else if (srpCondition) { 6994 status = srpCondition; 6995 } 6996 6997 /** 6998 * Handle price, year, and mileage as special cases since they can be either a range facet refinement or a numeric slider refinement depending on how the user has interacted with the filters. 6999 */ 7000 var priceBounds = getSdPriceBounds(helperState); 7001 var year = getSdYearValue(helperState); 7002 7003 var mileageRangeSelection = getSdStateFilterValues(helperState, ["mileageRange"]); 7004 var mileage = mileageRangeSelection !== "All" ? mileageRangeSelection : getSdNumericRangeValue(helperState, "mileage", function(v) { return Number(v).toLocaleString(); }); 7005 7006 return { 7007 status: status, 7008 minPrice: priceBounds.min, 7009 maxPrice: priceBounds.max, 7010 year: year, 7011 mileage: mileage, 7012 make: getSdStateFilterValues(helperState, ["make"]), 7013 model: getSdStateFilterValues(helperState, ["model"]), 7014 color: getSdStateFilterValues(helperState, ["genericColor", "generic_color"]), 7015 trim: getSdStateFilterValues(helperState, ["trim"]), 7016 bodyStyle: getSdStateFilterValues(helperState, ["body"]), 7017 features: getSdStateFilterValues(helperState, ["features"]), 7018 drivetrain: getSdStateFilterValues(helperState, ["drivetrain"]) 7019 }; 7020} 7021 7022/** 7023 * Creates a stable signature for the current search helper state so we can 7024 * detect real SRP refinement changes across renders. 7025 * 7026 * This is used only as change detection. The actual Shift Digital payload is 7027 * still built separately from the supported helper refinements. 7028 * 7029 * @returns {string} 7030 */ 7031function buildSdSearchStateSignature() { 7032 if (!search.helper || !search.helper.state) { 7033 return JSON.stringify({ 7034 query: "", 7035 disjunctiveFacetsRefinements: {}, 7036 facetsRefinements: {}, 7037 hierarchicalFacetsRefinements: {}, 7038 numericRefinements: {} 7039 }); 7040 } 7041 7042 return JSON.stringify({ 7043 query: search.helper.state.query || "", 7044 disjunctiveFacetsRefinements: search.helper.state.disjunctiveFacetsRefinements || {}, 7045 facetsRefinements: search.helper.state.facetsRefinements || {}, 7046 hierarchicalFacetsRefinements: search.helper.state.hierarchicalFacetsRefinements || {}, 7047 numericRefinements: search.helper.state.numericRefinements || {} 7048 }); 7049} 7050 7051/**
7052 * Builds a signature of only the facet/numeric refinement state (excludes 7053 * the search query) so facet-only changes can be distinguished from 7054 * query-only changes. 7055 * 7056 * @returns {string} 7057 */ 7058function buildSdFacetStateSignature() { 7059 if (!search.helper || !search.helper.state) { 7060 return JSON.stringify({ 7061 disjunctiveFacetsRefinements: {}, 7062 facetsRefinements: {}, 7063 hierarchicalFacetsRefinements: {}, 7064 numericRefinements: {} 7065 }); 7066 } 7067 7068 return JSON.stringify({ 7069 disjunctiveFacetsRefinements: search.helper.state.disjunctiveFacetsRefinements || {}, 7070 facetsRefinements: search.helper.state.facetsRefinements || {}, 7071 hierarchicalFacetsRefinements: search.helper.state.hierarchicalFacetsRefinements || {}, 7072 numericRefinements: search.helper.state.numericRefinements || {} 7073 }); 7074} 7075 7076/** 7077 * Sends the SRP pageview and filterSearch payload to Shift Digital for the 7078 * current search state. 7079 * 7080 * @returns {void} 7081 */ 7082function sendSdSrpPageViewAndFilterSearch() { 7083 sd('dataLayer', { 7084 pageType: 'Vehicle Listing', 7085 websiteTier: 'Tier 3', 7086 pageBrand: 'Toyota', 7087 sessionId: (window.daSessionId ? window.daSessionId() : ''), 7088 language: 'en', //note(ethan): need to change this to allow translations 7089 trafficType: 'Organic Search', 7090 dealerZipCode: '27896', 7091 dealerState: 'NC', 7092 dealerCity: 'Wilson', 7093 dealerName: '', 7094 dealerTda: 'SET10', 7095 siteTechnologyVersion: '2.0031', 7096 userZipCode: '', //note(ethan): add user location 7097 userCity: '', 7098 userState: '' 7099 }); 7100 sd('send', 'pageview'); 7101 7102 sd('dataLayer', { 7103 countSearchResults: $("#numberHits").text(), 7104 filterSearch: buildSdFilterSearchPayload(), 7105 events: 'filterSearch' 7106 }); 7107 sd('send'); 7108} 7109 7110/** 7111 * Sends the pageview and filterSearch owed to a query-only search. 7112 * 7113 * Called straight after typedSearch so Shift Digital sees 7114 * typedSearch -> pageview -> filterSearch, and off a timer when the query 7115 * changed without anything being typed. 7116 * 7117 * @returns {void} 7118 */ 7119function flushSdQueryAnalytics() { 7120 clearTimeout(sdQueryAnalyticsTimer); 7121 sdQueryAnalyticsTimer = null; 7122 7123 if (!sdQueryAnalyticsPending) { 7124 return; 7125 } 7126 7127 sdQueryAnalyticsPending = false; 7128 sendSdSrpPageViewAndFilterSearch(); 7129} 7130 7131/** 7132 * Watches InstantSearch render cycles and dispatches Shift Digital analytics 7133 * only when the underlying helper state has actually changed. 7134 * 7135 * The helper state signature prevents duplicate sends on unrelated renders 7136 * while still allowing select and deselect facet actions to be tracked. 7137 * 7138 * Facet changes send immediately. Query changes defer to flushSdQueryAnalytics 7139 * so typedSearch keeps its place at the front of the sequence. 7140 * 7141 * @returns {void} 7142 */ 7143function handleSdSrpRenderAnalytics() { 7144 if (!(haveSdAnalytics && typeof(sd) !== "undefined")) { 7145 return; 7146 } 7147 7148 if (!search.helper || !search.helper.lastResults) { 7149 return; 7150 } 7151 7152 var nextSdSearchStateSignature = buildSdSearchStateSignature(); 7153 var nextSdFacetStateSignature = buildSdFacetStateSignature(); 7154 var nextSdQuery = search.helper.state.query || ""; 7155 7156 if (lastSdSearchStateSignature === null) { 7157 lastSdSearchStateSignature = nextSdSearchStateSignature; 7158 lastSdFacetStateSignature = nextSdFacetStateSignature; 7159 lastSdQuery = nextSdQuery; 7160 return; 7161 } 7162 7163 var facetsChanged = nextSdFacetStateSignature !== lastSdFacetStateSignature; 7164 var queryChanged = nextSdQuery !== lastSdQuery; 7165 lastSdSearchStateSignature = nextSdSearchStateSignature; 7166 lastSdFacetStateSignature = nextSdFacetStateSignature; 7167 lastSdQuery = nextSdQuery; 7168 7169 if (facetsChanged) { 7170 // The facet send carries the current query too, so one send covers both. 7171 sdQueryAnalyticsPending = false; 7172 clearTimeout(sdQueryAnalyticsTimer); 7173 sdQueryAnalyticsTimer = null; 7174 7175 var deferAnalyticsUpdate = window.requestIdleCallback || function(callback) { 7176 setTimeout(callback, 0); 7177 }; 7178 7179 deferAnalyticsUpdate(function () { 7180 sendSdSrpPageViewAndFilterSearch(); 7181 }); 7182 7183 return; 7184 } 7185 7186 if (queryChanged) { 7187 sdQueryAnalyticsPending = true; 7188 clearTimeout(sdQueryAnalyticsTimer); 7189 sdQueryAnalyticsTimer = setTimeout(flushSdQueryAnalytics, 1200); 7190 } 7191} 7192 7193$(document).ready(function () { 7194 7195 // srp filter toggle buttons 7196 $(".srp-panel-toggle > span").click(function () { 7197 $(this).siblings("div").slideToggle("slow"); 7198 $(this).find("a > i").toggleClass("chevron-flip"); 7199 }); 7200 7201 $(document).on("input", ".ais-SearchBox-input", function() { 7202 clearTimeout(searchChangedTimer); 7203 searchChangedTimer = setTimeout(function() { 7204 if (haveSdAnalytics && typeof(sd) !== "undefined") { 7205 sd('dataLayer', { 7206 typedSearchContent: $(".ais-SearchBox-input").val().replace(/ /g, "|"), 7207 events: 'typedSearch' 7208 }); 7209 sd('send'); 7210 7211 // typedSearch is out the door, so the query's pageview and 7212 // filterSearch can follow it. 7213 flushSdQueryAnalytics(); 7214 } 7215 }, 800); 7216 }); 7217 7218 $(".showFiltersNonLegacy").click(function() { 7219 toggleFilters(); 7220 }); 7221 7222 $(".srp-filters-close-btn, .filterResultCount, .srpFilterResultCount").click(function() { 7223 toggleFilters(); 7224 }); 7225 7226 //Close mobile filters when a search is entered 7227 $('input[type=search]').on('search', function () { 7228 if ($('.side-panel-container').hasClass('mobileFilters')) 7229 { 7230 toggleFilters(); 7231 } 7232 }); 7233 7234 // Clear filters and set the filters bar back to the normal color 7235 $("#dv-srp-clear-filters, #srp-filters-reset-btn").click(function() { 7236 search.helper.setQuery('').search(); 7237 }); 7238 7239 // Clear Search bar 7240 $("#clearSearchResults").click(function() { 7241 document.querySelector('#clearSearchResults').style.display = "none"; 7242 search.helper.setQuery('').search(); 7243 }); 7244 7245 var placeholderText = [ 7246 ]; 7247 7248 var placeholderTextVoice = [ 7249 "Listening, Say \"Show Me a Red " + new Date().getFullYear() + " Toyota with Navigation\"", 7250 ]; 7251 7252 //Change mobile filters bar when text is typed in the searchbar 7253 $('.ais-SearchBox-input').change(function () { 7254 $('.showFiltersNonLegacy').css('background-color', '#000000'); 7255 $('.showFiltersNonLegacy').css('color', '#FFFFFF'); 7256 }) 7257 7258 //Make vehicle cars click into the VDP 7259 $(document.body).on("click", ".car-title, .srp-slider-buttons, .srp-click-image", function (e) { 7260 var vehicle_url = $(this).parents(".listing-container").attr("data-url") 7261 if (vehicle_url) { 7262 window.location = vehicle_url; 7263 } else { 7264 console.warn("`vehicle_url` was not found on the .listing-container"); 7265 } 7266 }); 7267 7268 7269 $('.year-container > div').slideToggle("slow"); 7270 $(".year-container > span > a > i").toggleClass("chevron-flip"); 7271 7272 7273 $('.pricerange-container > div').slideToggle("slow"); 7274 $(".pricerange-container > span > a > i").toggleClass("chevron-flip"); 7275 7276 7277 $('.mileagerange-container > div').slideToggle("slow"); 7278 $(".mileagerange-container > span > a > i").toggleClass("chevron-flip"); 7279 7280 7281 $('.body-container > div').slideToggle("slow"); 7282 $(".body-container > span > a > i").toggleClass("chevron-flip"); 7283 7284 7285 $('.fuel-container > div').slideToggle("slow"); 7286 $(".fuel-container > span > a > i").toggleClass("chevron-flip"); 7287 7288 7289 $('.transmission-container > div').slideToggle("slow"); 7290 $(".transmission-container > span > a > i").toggleClass("chevron-flip"); 7291 7292 7293 $('.color-container > div').slideToggle("slow"); 7294 $(".color-container > span > a > i").toggleClass("chevron-flip"); 7295 7296 7297 $('.drivetrain-container > div').slideToggle("slow"); 7298 $(".drivetrain-container > span > a > i").toggleClass("chevron-flip"); 7299 7300 7301 $('.location-container > div').slideToggle("slow"); 7302 $(".location-container > span > a > i").toggleClass("chevron-flip"); 7303 7304 7305 $('.mpg-hway-container > div').slideToggle("slow"); 7306 $(".mpg-hway-container > span > a > i").toggleClass("chevron-flip"); 7307 7308 7309 $('.mpg-city-container > div').slideToggle("slow"); 7310 $(".mpg-city-container > span > a > i").toggleClass("chevron-flip"); 7311 7312 7313 $('.features-container > div').slideToggle("slow"); 7314 $(".features-container > span > a > i").toggleClass("chevron-flip"); 7315 7316 7317 $('.fa-microphone').toggleClass('fal fas fa-microphone fa-search'); 7318 //$('.ais-SearchBox-input').placeholderTypewriter({text: placeholderText}); 7319 7320 if (haveSdAnalytics && typeof(sd) !== "undefined") 7321 { 7322 // header.php has already sent the pageview for this load, so this 7323 // keeps the pageview -> filterSearch order Shift Digital asked for. 7324 sd('dataLayer', { 7325 countSearchResults: $("#numberHits").text(), 7326 filterSearch: buildSdFilterSearchPayload(), 7327 events: 'filterSearch' 7328 }); 7329 sd('send'); 7330 7331 sdInitialFilterSearchSent = true; 7332 7333 if (sdFormShownPending) { 7334 sd('dataLayer', { 7335 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 7336 displayType: 'modal', 7337 events: 'formShown' 7338 }); 7339 sd('send'); 7340 sdFormShownPending = false;
7341 } 7342 } 7343 }); 7344 7345 function voiceSearch(term) 7346 { 7347 term = term.toLowerCase(); 7348 let searchBox = document.querySelector('.ais-SearchBox-input'); 7349 searchBox.value = term; 7350 searchBox.dispatchEvent(new Event('input')); 7351 } 7352</script>
vendor: 1 bytes, line 7352
7352
7353<script> 7354 7355var popupFormCalled = false; 7356var currentVehicleData = null; 7357var currentFormType = null; 7358 7359 //Open the form 7360 function popupForm(vin) { 7361 7362 if (popupFormCalled) { 7363 console.log('Prevented duplicate popupForm call'); 7364 return; 7365 } 7366 7367 popupFormCalled = true; 7368 setTimeout(function() { 7369 popupFormCalled = false; 7370 }, 500); 7371 7372 $(".cd-panel").addClass("cd-panel--is-visible"); 7373 $("body").delay(300).queue(function (next) { 7374 $(this).addClass("cd-panel-no-scroll"); 7375 next(); 7376 }); 7377 $(".right-half, #nav-icon1, #nav-icon2, #nav-icon3, #nav-icon4").delay(300).queue(function (next) { 7378 $(this).addClass("cd-panel-subheader-no-scroll"); 7379 next(); 7380 }); 7381 7382 if (vin === "payment_calculator_container") { 7383 $(".popup_form#srp_form_container").hide(); 7384 $("#payment_calculator_container").show(); 7385 calculate(); 7386 var selected_form_title = $(".gform_title", selected_form).text(); 7387 $("#popup_left_title").html(selected_form_title); 7388 } else { 7389 var selected_form = $(".popup_form#srp_form_container"); 7390 var selected_form_title = $(".gform_title", selected_form).text(); 7391 $("#popup_left_title").html(selected_form_title); 7392 } 7393 7394 if (haveSdAnalytics && typeof(sd) !== "undefined" && vin !== 'payment_calculator_container') 7395 { 7396 window.currentVin = vin; 7397 7398 $.post("/app/themes/dv-framework/ajax/sdformvehicle.php", {vin: vin}, function (data) { 7399 7400 setTimeout(function() { 7401 7402 sd('dataLayer', { 7403 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text()), 7404 displayType: 'modal', 7405 events: 'formShown' 7406 }); 7407 sd('send'); 7408 7409 currentVehicleData = JSON.parse(data); 7410 currentFormType = getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]) 7411 7412 var formInitHandled = false; 7413 $('.gform_wrapper input').click(function() { 7414 if (!formInitHandled) 7415 { 7416 sendShiftDigitalFormEvent({ 7417 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 7418 displayType: 'modal', 7419 eventName: 'formInitiation' 7420 }); 7421 7422 formInitHandled = true; 7423 } 7424 }); 7425 $('.gform_wrapper input, .gform_wrapper textarea, .gform_wrapper select').on('input change', function() { 7426 if (shouldTrackShiftDigitalFieldInteraction(this)) 7427 { 7428 sendShiftDigitalFormEvent({ 7429 formType: getSDFormType($(".gform_title", $(".popup_form#srp_form_container")).text(), $(".popup_form#srp_form_container form")[0]), 7430 displayType: 'modal', 7431 eventName: 'formFieldInteraction', 7432 fieldTarget: this 7433 }); 7434 } 7435 }); 7436 }, 1000); 7437 }); 7438 } 7439 } 7440 7441 //Non confirmation page form submission for SD Analytics 7442 jQuery(document).ready(function(){ 7443 jQuery(document).on("gform_confirmation_loaded.vehicleForm", function(event, formId){ 7444 7445 if (haveSdAnalytics && typeof(sd) !== "undefined" && currentVehicleData) { 7446 7447 sd('dataLayer', { 7448 formType: currentFormType, 7449 displayType: 'modal', 7450 events: 'formSubmission', 7451 formVehicle: currentVehicleData, 7452 leadType: 'lead' 7453 }); 7454 sd('send'); 7455 7456 currentVehicleData = null; 7457 currentFormType = null; 7458 } 7459 }); 7460 }); 7461 7462 //Incentives Slide out 7463 // Wait for element to become available 7464 function waitForElement(selector) { 7465 return new Promise(resolve => { 7466 if (document.querySelector(selector)) { 7467 return resolve(document.querySelector(selector)); 7468 } 7469 7470 console.log("waiting for element"); 7471 7472 const observer = new MutationObserver(mutations => { 7473 if (document.querySelector(selector)) { 7474 observer.disconnect(); 7475 resolve(document.querySelector(selector)); 7476 } 7477 }); 7478 7479 // If you get "parameter 1 is not of type 'Node'" error, see https://stackoverflow.com/a/77855838/492336 7480 observer.observe(document.body, { 7481 childList: true, 7482 subtree: true 7483 }); 7484 }); 7485 } 7486 7487 function initForms() 7488 { 7489 disableForms(); 7490 7491 $('.srp_cta_1').click(function () { 7492 var vin = $(this).attr("data-vehicle-vin"); 7493 $("#popup_left_dealer").html($(this).attr("data-dealer-name")); 7494 $("#popup_left_price").html($(this).attr("data-vehicle-price")); 7495 $("#popup_left_stock_number").html($(this).attr("data-vehicle-stock-number")); 7496 $("#popup_left_vin").html($(this).attr("data-vehicle-vin")); 7497 $("#popup_left_vehicle_title").html($(".vehicle_title_form", $(this)).text()); 7498 getCTAForm($(this).attr("data-vehicle-id"), $(this).attr("data-vehicle-vin"), $(this).attr("data-vehicle-discount"), 27); 7499 popupForm(vin); 7500 event.stopPropagation(); 7501 }); 7502 $('.srp_cta_2').click(function () { 7503 var vin = $(this).attr("data-vehicle-vin"); 7504 $("#popup_left_dealer").html($(this).attr("data-dealer-name")); 7505 $("#popup_left_price").html($(this).attr("data-vehicle-price")); 7506 $("#popup_left_stock_number").html($(this).attr("data-vehicle-stock-number")); 7507 $("#popup_left_vin").html($(this).attr("data-vehicle-vin")); 7508 $("#popup_left_vehicle_title").html($(".vehicle_title_form", $(this)).text()); 7509 getCTAForm($(this).attr("data-vehicle-id"), $(this).attr("data-vehicle-vin"), $(this).attr("data-vehicle-discount"), 6); 7510 popupForm(vin); 7511 event.stopPropagation(); 7512 }); 7513 7514 $(".autocheck_button").on("click", function () { 7515 var vin = $(this).attr("data-vehicle-vin"); 7516 $("#popup_left_dealer").html($(this).attr("data-dealer-name")); 7517 $("#popup_left_price").html($(this).attr("data-vehicle-price")); 7518 $("#popup_left_stock_number").html($(this).attr("data-vehicle-stock-number")); 7519 $("#popup_left_vin").html($(this).attr("data-vehicle-vin")); 7520 $("#popup_left_vehicle_title").html($(".vehicle_title_form", $(this)).text()); 7521 $(".cd-panel__content").css({"padding-top": "114px"}); 7522 $(".cd-panel__container").css({"width": "100%"}); 7523 $(".cd-panel__header").css({"width": "100%"}); 7524 getAutoCheckReport($(this).attr("data-vehicle-id")); 7525 popupForm(vin); 7526 event.stopPropagation(); 7527 }); 7528 7529 $('.srp-cta-calculate-payment-btn').click(function () { 7530 const parentListing = $(this).closest('.listing'); 7531 const priceVal = parentListing.data('ag-price'); 7532 $('#carPrice').val(priceVal || 0); 7533 $("#popup_left_vin").html($(this).attr("data-vehicle-vin")); 7534 $("#popup_left_vehicle_title").html($(".vehicle_title_form", $(this)).text()); 7535 popupForm("payment_calculator_container"); 7536 event.stopPropagation(); 7537 }); 7538 7539 7540 //Button click to close, click outside form to close 7541 $(".cd-panel__close, .cd-panel__otherside").click(function () { 7542 $(".cd-panel").removeClass("cd-panel--is-visible"); 7543 $("#payment_calculator_container").delay(400).hide(0); 7544 $(".popup_form").delay(400).hide(0); 7545 $(".popup_form").delay(400).queue(function (next) { 7546 $(this).empty(); 7547 next(); 7548 }); 7549 $("body").delay(400).queue(function (next) { 7550 $(this).removeClass("cd-panel-no-scroll"); 7551 next(); 7552 }); 7553 $(".right-half, #nav-icon1, #nav-icon2, #nav-icon3, #nav-icon4").delay(400).queue(function (next) { 7554 $(this).removeClass("cd-panel-subheader-no-scroll"); 7555 next(); 7556 }); 7557 $(".cd-panel__content").removeAttr('style'); 7558 $(".listing").removeAttr('style'); 7559 $(".cd-panel__subheader-right").show(); 7560 setTimeout(function () { 7561 $(".cd-panel__container").removeAttr('style'); 7562 }, 300); 7563 }); 7564 } 7565 7566 function disableForms() 7567 { 7568
7569 $('.srp_cta_1').off("click"); 7570 $('.srp_cta_2').off("click"); 7571 7572 $(".autocheck_button").off("click"); 7573 $(".cd-panel__close, .cd-panel__otherside").off("click"); 7574 } 7575 7576 function toggleFilters() 7577 { 7578 $(".side-panel-container").toggleClass("mobileFilters"); 7579 $(".showFiltersNonLegacy i").toggleClass("chevron-flip"); 7580 $(".result-wrapper").toggleClass("filtersOpen"); 7581 $("body").toggleClass("filtersOpen"); 7582 $(".filterResultCount").toggleClass("filter-result-count-active"); 7583 } 7584 7585 /** 7586 * Retry counter lives outside the function on purpose. 7587 * 7588 * It used to be `let tries = 0` as the first statement inside, which reset it 7589 * to zero on every call - so `tries < 10` could never fail and the "retry ten 7590 * times" guard was in fact an unbounded one-second loop for as long as the page 7591 * stayed open. It does not fire where DG loads normally, but it does on any 7592 * dealer where DG is slow, blocked, or absent. 7593 * 7594 * Logging is behind ?spdebug=1 for the same reason the rest of this moved to 7595 * onRenderSettled: console.log of a populated vehicle array on every render is 7596 * not free, and it is markedly worse in Safari with an inspector attached - 7597 * which is exactly the situation anyone debugging this on an iPhone is in. 7598 */ 7599 var smartPathTries = 0; 7600 var smartPathDebug = new URLSearchParams(window.location.search).get('spdebug') === '1'; 7601
7602 function renderSmartPath() 7603 { 7604 if (smartPathDebug) console.log("Trying to render smartpath objects..."); 7605 7606 if (typeof window.DGDataHub.getWarningState !== "undefined" && (window.DGDataHub.getWarningState().dgLoaded || smartPathDebug)) 7607 { 7608 var smartPathVehicles = vehiclesList.map(veh => ({ 7609 type: 'inv', 7610 brand: veh.make, 7611 modelCd: veh.modelCode, 7612 dealerCd: '32136', 7613 advertisedPrice: parseFloat(veh.internetPrice.replace("$", "").replace(",", "")), // Advertised Price 7614 imageHref: veh.imageUrls[0], 7615 imagePrice: 0, 7616 marketingSeries: veh.model, 7617 marketingName: veh.model, 7618 year: veh.yr, 7619 vin: veh.vin, 7620 price: parseFloat(veh.msrp.replace("$", "").replace(",", "")), // MSRP 7621 ePrice: parseFloat(veh.finalPrice.replace("$", "").replace(",", "")), // Selling Price 7622 vdpHref: veh.vdpUrl, 7623 vlpHref: `http://www.toyota.com/${veh.model.toLowerCase()}/`, 7624 salesClass: veh.certified == "yes" ? 'cpo' : veh.condition.toLowerCase(), // value options are 'new', 'used' and 'cpo' (certified pre-owned), 7625 vehicleType: veh.certified == "yes" ? 'cpo' : veh.condition.toLowerCase() // value options are 'new', 'used' and 'cpo' (certified pre-owned), 7626 })); 7627 7628 var saveItemsObj = {} 7629 7630 smartPathVehicles.map(veh => saveItemsObj[`dg-inline-save-inv-${veh.vin}`] = veh); 7631 7632 if (smartPathDebug) console.log(smartPathVehicles); 7633 7634 window.DGDataHub.renderInlineSaves(saveItemsObj); 7635 7636 7637 if (smartPathDebug) console.log(window.DGDataHub.getDgid()); 7638 7639 fetch("https://mobile-api.rti.toyota.com/leads/garage/eprice?dgid=" + window.DGDataHub.getDgid() + "&dealerCd=" + "32136").then(response => response.json()).then(data => { 7640 if (data.includes("32136") && srpCondition != "Used") 7641 { 7642 if (smartPathDebug) console.log("Unlocking smartprice..."); 7643 $(".dv-pricinggate").show(); 7644 $(".dv-pricing-main").hide(); 7645 $(".srp_cta_pricinggate").hide(); 7646 $(".srp-cta-smartpath1-btn").hide(); 7647 $(".srp-cta-smartpathunlocked-btn").attr('style', 'display: inline !important'); 7648 7649 $(".vehicle-price-container").css('height', ''); 7650 } 7651 7652 return data; 7653 }).then(data => { if (smartPathDebug) console.log(data); }); 7654 } 7655 else 7656 { 7657 if (smartPathTries < 10) 7658 { 7659 smartPathTries++; 7660 setTimeout(renderSmartPath, 1000); 7661 } 7662 } 7663 } 7664 7665 function checkAndRemoveFacets() { 7666 7667 if (!userInteractedWithFacets) return; 7668 7669 // Remove child facet if parent facet is unclicked 7670 if(srpCondition === "Used" || srpDealerId.includes(dealerGroupSite)){ 7671 if($("#model-list ul li input[type='checkbox']:checked").length > 0 && $("#make-list ul li input[type='checkbox']:checked").length === 0){ 7672 search.helper.removeDisjunctiveFacetRefinement('model'); 7673 search.helper.removeDisjunctiveFacetRefinement('trim'); 7674 search.helper.search(); 7675 userInteractedWithFacets = false; 7676 } 7677 } 7678 7679 if($("#trim-list ul li input[type='checkbox']:checked").length > 0 && $("#model-list ul li input[type='checkbox']:checked").length === 0){ 7680 search.helper.removeDisjunctiveFacetRefinement('trim'); 7681 search.helper.search(); 7682 userInteractedWithFacets = false; 7683 } 7684 } 7685 7686 function getUrlParams() { 7687 7688 const params = new URLSearchParams(window.location.search); 7689 const paramObj = {}; 7690 params.forEach((value, key) => { 7691 7692 if (!paramObj[key]) { 7693 7694 paramObj[key] = []; 7695 } 7696 paramObj[key].push(value); 7697 }); 7698 return paramObj; 7699 } 7700 7701 // Function to dynamically toggle filters based on URL params 7702 function toggleFiltersDynamically() { 7703 const params = getUrlParams(); 7704 7705 Object.keys(params).forEach(function(filterVar) { 7706 7707 filterVar = filterVar.toLowerCase(); 7708 7709 if(filterVar == "genericcolor"){ 7710 filterVar = "color"; 7711 } 7712 7713 if(filterVar == "finalpricerange"){ 7714 filterVar = "pricerange"; 7715 } 7716 7717 if(filterVar == "yr"){ 7718 filterVar = "year"; 7719 } 7720 7721 if(filterVar == "transmissiontype"){ 7722 filterVar = "transmission"; 7723 } 7724 7725 const containerSelector = $(`.${filterVar}-container > div`); 7726 7727 if (containerSelector.length > 0) { 7728 containerSelector.show(); 7729 } 7730 }); 7731 } 7732 7733 7734 //Nexus Fuse Payments Start 7735 7736 //Fuse Payments Button - Nexus 7737 function nexusPaymentButtons(){ 7738 7739 } 7740 7741 7742 function updateFuseButton(buttonContainer, data, offerTypeId) { 7743 7744 if (!data || !Array.isArray(data)) { 7745 console.error('Error in updateFuseButton: "data" is either undefined or not an array.', { data, buttonContainer, offerTypeId }); 7746 buttonContainer.style.display = 'none'; 7747 return; 7748 } 7749 7750 const matchedOffer = data.find(offer => offer.fuse.OfferTypeID == offerTypeId); 7751 7752 if (matchedOffer) { 7753 7754 //Used for Fuse SinglePaymentOption 7755 const fuseOfferOne = "5"; 7756 7757 //Used for Fuse APR 7758 const fuseOfferTwo = "7"; 7759 7760 //Used for Fuse PaymentNoTax 7761 const fuseOfferThree = "5"; 7762 7763 let ctaText = ""; 7764 let buttonHtml = ""; 7765 let ctaDisclaimer = ""; 7766 7767 if(matchedOffer.fuse.OfferTypeID == fuseOfferOne && fuseOfferOne !== "1") { 7768 const ctaFuseText = "Single Payment Option"; 7769 const singlePayment = matchedOffer.fuse.SinglePayment; 7770 7771 function formatAsCurrency(amount) {
7772 return amount.toLocaleString('en-US', { 7773 minimumFractionDigits: 0, 7774 maximumFractionDigits: 0 7775 }); 7776 } 7777 7778 const formattedPayment = formatAsCurrency(singlePayment); 7779 7780 ctaFuseAmount = formattedPayment 7781 ctaDisclaimer = matchedOffer.fuse.Disclaimer; 7782 7783 buttonHtml = ` 7784 <a href='javascript: void(0);' data-vehicle-id="${matchedOffer.vin}" data-vehicle-vin="${buttonContainer.getAttribute('data-vehicle-vin')}" data-vehicle-condition="${buttonContainer.getAttribute('data-vehicle-condition')}" data-vehicle-year="${buttonContainer.getAttribute('data-vehicle-year')}" data-vehicle-make="${buttonContainer.getAttribute('data-vehicle-make')}" data-vehicle-model="${buttonContainer.getAttribute('data-vehicle-model')}" data-vehicle-stock-number="${buttonContainer.getAttribute('data-vehicle-stock-number')}" data-vehicle-price="${buttonContainer.getAttribute('data-vehicle-price')}" data-vehicle-discount="${buttonContainer.getAttribute('data-vehicle-discount')}" data-dealer-name="${buttonContainer.getAttribute('data-dealer-name')}" data-dealer-id="${buttonContainer.getAttribute('data-dealer-id')}" data-form-id="${buttonContainer.getAttribute('data-form-id')}" data-offer-type-id="${offerTypeId}" data-customer-disclaimer="${ctaDisclaimer}" class="${buttonContainer.className}"> 7785 <span class="option-title">${ctaFuseText}</span> 7786 <span class="option-value">$${ctaFuseAmount}</span> 7787 <span style="display:none;" class="vehicle_title_form">${buttonContainer.getAttribute('data-vehicle-year')} ${buttonContainer.getAttribute('data-vehicle-make')} ${buttonContainer.getAttribute('data-vehicle-model')} </span> 7788 </a> 7789 `; 7790 } 7791 7792 if(matchedOffer.fuse.OfferTypeID == fuseOfferTwo){ 7793 const ctaFuseText = "APR"; 7794 const ctaFuseAmount = `${matchedOffer.fuse.APR}%`; 7795 ctaDisclaimer = matchedOffer.fuse.Disclaimer; 7796 7797 buttonHtml = ` 7798 <a href='javascript: void(0);' data-vehicle-id="${matchedOffer.vin}" data-vehicle-vin="${buttonContainer.getAttribute('data-vehicle-vin')}" data-vehicle-condition="${buttonContainer.getAttribute('data-vehicle-condition')}" data-vehicle-year="${buttonContainer.getAttribute('data-vehicle-year')}" data-vehicle-make="${buttonContainer.getAttribute('data-vehicle-make')}" data-vehicle-model="${buttonContainer.getAttribute('data-vehicle-model')}" data-vehicle-stock-number="${buttonContainer.getAttribute('data-vehicle-stock-number')}" data-vehicle-price="${buttonContainer.getAttribute('data-vehicle-price')}" data-vehicle-discount="${buttonContainer.getAttribute('data-vehicle-discount')}" data-dealer-name="${buttonContainer.getAttribute('data-dealer-name')}" data-dealer-id="${buttonContainer.getAttribute('data-dealer-id')}" data-form-id="${buttonContainer.getAttribute('data-form-id')}" data-offer-type-id="${offerTypeId}" data-customer-disclaimer="${ctaDisclaimer}" class="${buttonContainer.className}"> 7799 <span class="option-title">${ctaFuseText}</span> 7800 <span class="option-value">${ctaFuseAmount}</span> 7801 <span style="display:none;" class="vehicle_title_form">${buttonContainer.getAttribute('data-vehicle-year')} ${buttonContainer.getAttribute('data-vehicle-make')} ${buttonContainer.getAttribute('data-vehicle-model')} </span> 7802 </a> 7803 `; 7804 } 7805 7806 //Fuse option 3 used for offerTypeId 1 PaymentNoTax 7807 if(matchedOffer.fuse.OfferTypeID == fuseOfferThree && (matchedOffer.fuse.OfferTypeID == 1 && fuseOfferOne === "1")){ 7808 const ctaFuseText = "Single Payment Option"; 7809 const ctaFuseAmount = `${matchedOffer.fuse.PaymentNoTax}`; 7810 ctaDisclaimer = matchedOffer.fuse.Disclaimer; 7811 7812 const textResult = replaceAmountPlaceholder(ctaFuseText, ctaFuseAmount); 7813 7814 if (textResult.hasPlaceholder) { 7815 buttonHtml = ` 7816 <a href='javascript: void(0);' data-vehicle-id="${matchedOffer.vin}" data-vehicle-vin="${buttonContainer.getAttribute('data-vehicle-vin')}" data-vehicle-condition="${buttonContainer.getAttribute('data-vehicle-condition')}" data-vehicle-year="${buttonContainer.getAttribute('data-vehicle-year')}" data-vehicle-make="${buttonContainer.getAttribute('data-vehicle-make')}" data-vehicle-model="${buttonContainer.getAttribute('data-vehicle-model')}" data-vehicle-stock-number="${buttonContainer.getAttribute('data-vehicle-stock-number')}" data-vehicle-price="${buttonContainer.getAttribute('data-vehicle-price')}" data-vehicle-discount="${buttonContainer.getAttribute('data-vehicle-discount')}" data-dealer-name="${buttonContainer.getAttribute('data-dealer-name')}" data-dealer-id="${buttonContainer.getAttribute('data-dealer-id')}" data-form-id="${buttonContainer.getAttribute('data-form-id')}" data-offer-type-id="${offerTypeId}" data-customer-disclaimer="${ctaDisclaimer}" class="${buttonContainer.className}"> 7817 <span class="option-title">${textResult.displayText}</span> 7818 <span style="display:none;" class="vehicle_title_form">${buttonContainer.getAttribute('data-vehicle-year')} ${buttonContainer.getAttribute('data-vehicle-make')} ${buttonContainer.getAttribute('data-vehicle-model')} </span> 7819 </a> 7820 `; 7821 } else { 7822 buttonHtml = `
7823 <a href='javascript: void(0);' data-vehicle-id="${matchedOffer.vin}" data-vehicle-vin="${buttonContainer.getAttribute('data-vehicle-vin')}" data-vehicle-condition="${buttonContainer.getAttribute('data-vehicle-condition')}" data-vehicle-year="${buttonContainer.getAttribute('data-vehicle-year')}" data-vehicle-make="${buttonContainer.getAttribute('data-vehicle-make')}" data-vehicle-model="${buttonContainer.getAttribute('data-vehicle-model')}" data-vehicle-stock-number="${buttonContainer.getAttribute('data-vehicle-stock-number')}" data-vehicle-price="${buttonContainer.getAttribute('data-vehicle-price')}" data-vehicle-discount="${buttonContainer.getAttribute('data-vehicle-discount')}" data-dealer-name="${buttonContainer.getAttribute('data-dealer-name')}" data-dealer-id="${buttonContainer.getAttribute('data-dealer-id')}" data-form-id="${buttonContainer.getAttribute('data-form-id')}" data-offer-type-id="${offerTypeId}" data-customer-disclaimer="${ctaDisclaimer}" class="${buttonContainer.className}"> 7824 <span class="option-title">${textResult.displayText}</span> 7825 <span class="option-value">$${ctaFuseAmount}</span> 7826 <span style="display:none;" class="vehicle_title_form">${buttonContainer.getAttribute('data-vehicle-year')} ${buttonContainer.getAttribute('data-vehicle-make')} ${buttonContainer.getAttribute('data-vehicle-model')} </span> 7827 </a> 7828 `; 7829 } 7830 } 7831 7832 let newButtonElement = document.createRange().createContextualFragment(buttonHtml).firstElementChild; 7833 buttonContainer.replaceWith(newButtonElement); 7834 7835 fuseButtonBinding(); 7836 } else { 7837 console.log("No matching offer found for OfferTypeID:", offerTypeId); 7838 } 7839 } 7840 7841 7842 function replaceAmountPlaceholder(text, amount) { 7843 if (text.includes('{amount}')) { 7844 return { 7845 hasPlaceholder: true, 7846 displayText: text.replace('{amount}', `<span class="option-value">$${amount}</span>`) 7847 }; 7848 } 7849 return { 7850 hasPlaceholder: false, 7851 displayText: text 7852 }; 7853 } 7854 7855 function fuseButtonBinding(){ 7856 } 7857 //Nexus Fuse Payments End 7858 7859 7860 7861 $(document).ready(function () { 7862 // if (navigator.platform == "MacIntel") 7863 // { 7864 // $(".srp-results").css("width", "calc(100vw - 376px)"); 7865 // } 7866 7867 7868 setTimeout(function(){ 7869 7870 toggleFiltersDynamically(); 7871 nexusPaymentButtons(); 7872 initForms(); 7873 registerSmartpathCTAOverrides(jQuery("#srp-results")); 7874 }, 1000); 7875 }); 7876</script>
7876 7877 7878 7879
7880<script type="text/javascript"> 7881(function(w,d,s,o,f,js,fjs){ 7882 w['UnlockPrice']=o;w[o]=w[o]||function(){(w[o].q=w[o].q||[]).push(arguments)}; 7883 js=d.createElement(s),fjs=d.getElementsByTagName(s)[0]; 7884 js.id=o;js.src=f;js.async=1;fjs.parentNode.insertBefore(js,fjs); 7885}(window,document,'script','runmylease','https://runmylease-products.s3.us-east-1.amazonaws.com/unlockprice/toyota/hubertvestertoyota.js')); 7886runmylease('init',{dealerCode: '6840802a4a6b1374988fe463'}); 7887</script>
7887 7888</main> 7889<div class="srp-bottom-disclaimers"> 7890<h4>Disclaimer</h4> 7891All pricing and details are believed to be accurate, but we do not warrant or guarantee such accuracy. The prices shown above, may vary from region to region, as will incentives, and are subject to change. Vehicle information is based off standard equipment and may vary from vehicle to vehicle. Call or email for complete vehicle specific information. Dealer not responsible for typographical errors. All prices exclude tax, tags, title, registration. Price includes $799.00 dealer fee. All pricing reflects dealer retaining all dealer cash and available customer incentive. Dealer Administrative Charge is not included in advertised price. All prices and offers are before state, city and county tax, tag, title and license fees. Out of state buyers are responsible for all state, county, city taxes and fees, as well as title/registration fees in the state that the vehicle will be registered. All prices and offers include all factory rebates and incentives which the dealer retains unless otherwise specifically provided. Dealer not responsible for errors and omissions; all offers subject to change without notice, please confirm listings with dealer. By filling out this form, you authorize our dealership to call, text, or email you in the future. 7892<br><br> 7893While great effort is made to ensure the accuracy of the information on this site, errors do occur so please verify information with a customer service rep. This is easily done by calling us at (252) 293-6513 or by visiting us at the dealership. 7894<br><br> 7895**With approved credit. Terms may vary. Monthly payments are only estimates derived from the vehicle price with a 72 month term, 4.9% interest and 20% downpayment. 7896<br><br> 7897<b>MPG Disclaimer:</b> 7898<br>Based on EPA mileage ratings. Use for comparison purposes only. Your actual mileage will vary depending on how you drive and maintain your vehicle. 7899<br><br> 7900<b>The Vester Promise Disclaimer:</b> Your vehicle's final trade-in value is set by the dealer after inspection and is affected by vehicle condition, mileage, vehicle history, repairs and other factors. 7901</div>
7901<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/video.js?v=1.648.51"></script>
7901 7902<style> 7903 /*****************************************************************************************************************************/ 7904 /* CTA 1 Button */ 7905 /*****************************************************************************************************************************/ 7906 .srp-cta-1-btn { 7907 color: #ffffff !important; 7908 background-color: #eb0a1e !important; 7909 } 7910 7911 .srp-cta-1-btn:hover { 7912 background-color: #383838 !important; 7913 } 7914 7915 /*****************************************************************************************************************************/ 7916 /* CTA 2 Button */ 7917 /*****************************************************************************************************************************/ 7918 .srp-cta-2-btn { 7919 color: #ffffff !important; 7920 background-color: #d50000 !important; 7921 } 7922 7923 .srp-cta-2-btn:hover { 7924 background-color: #000000 !important; 7925 } 7926 7927 /*****************************************************************************************************************************/ 7928 /* CTA 3 Button */ 7929 /*****************************************************************************************************************************/ 7930 .srp-cta-3-btn { 7931 color: #ffffff !important; 7932 background-color: #000000 !important; 7933 } 7934 7935 .srp-cta-3-btn:hover { 7936 background-color: #eeeeee !important; 7937 } 7938 7939 7940 /*****************************************************************************************************************************/ 7941 /* CTA 4 Button */ 7942 /*****************************************************************************************************************************/ 7943 .srp-cta-4-btn { 7944 color: #ffffff !important; 7945 background-color: #000000 !important; 7946 } 7947 7948 .srp-cta-4-btn:hover { 7949 background-color: #eeeeee !important; 7950 } 7951 7952 /*****************************************************************************************************************************/ 7953 /* CTA 5 Button */ 7954 /*****************************************************************************************************************************/ 7955 .srp-cta-5-btn { 7956 color: #ffffff !important; 7957 background-color: #262626 !important; 7958 } 7959 7960 .srp-cta-5-btn:hover { 7961 background-color: #0a0a0a !important; 7962 } 7963 7964 /*****************************************************************************************************************************/ 7965 /* CTA 6 Button */ 7966 /*****************************************************************************************************************************/ 7967 .srp-cta-6-btn { 7968 color: #ffffff !important; 7969 background-color: #262626 !important; 7970 } 7971 7972 .srp-cta-6-btn:hover { 7973 background-color: #0a0a0a !important; 7974 } 7975 7976 /*****************************************************************************************************************************/ 7977 /* Roadster CTA Button */ 7978 /*****************************************************************************************************************************/ 7979 .srp-cta-roadster-btn { 7980 color: #063497 !important; 7981 background-color: #ffcc00 !important; 7982 } 7983 7984 /*****************************************************************************************************************************/ 7985 /* Custom Modal CTA Button */ 7986 /*****************************************************************************************************************************/ 7987 .srp-cta-modal-btn { 7988 color: #ffffff; 7989 background-color: #eb0a1e; 7990 } 7991 7992 .srp-cta-modal-btn:hover { 7993 color: #ffffff; 7994 background-color: #000000; 7995 } 7996 7997 .srp-cta-modal-btn-two { 7998 color: #000000; 7999 background-color: #eb0a1e; 8000 } 8001 8002 .srp-cta-modal-btn-two:hover { 8003 color: #000000; 8004 background-color: #eb0a1e; 8005 } 8006 8007 /*****************************************************************************************************************************/ 8008 /* Pricing Gate Button */ 8009 /*****************************************************************************************************************************/ 8010 .srp-cta-pricinggate-btn { 8011 color: #ffffff !important; 8012 background-color: #000000 !important; 8013 } 8014 8015 .srp-cta-pricinggate-btn:hover { 8016 color: #eeeeee !important; 8017 background-color: #eeeeee !important; 8018 } 8019 8020 /*****************************************************************************************************************************/ 8021 /* CTA Calculate Payment Button */ 8022 /*****************************************************************************************************************************/ 8023 .srp-cta-calculate-payment-btn { 8024 color: white; 8025 background-color: var(--primary-color); 8026 border-color: var(--primary-color); 8027 } 8028 8029 .srp-cta-calculate-payment-btn:hover { 8030 color: white; 8031 background-color: var(--secondary-color); 8032 border-color: var(--secondary-color); 8033 } 8034 8035 8036 /*****************************************************************************************************************************/ 8037 /* Instant Search Styles */ 8038 /*****************************************************************************************************************************/ 8039 8040 .ais-Pagination-item--firstPage .ais-Pagination-link, .ais-Pagination-item--previousPage .ais-Pagination-link, .ais-Pagination-item--nextPage .ais-Pagination-link, .ais-Pagination-item--lastPage .ais-Pagination-link { 8041 color: #eb0a1e; 8042 } 8043 8044 .ais-RefinementList-count { 8045 color: #eb0a1e; 8046 font-weight: bold; 8047 } 8048 8049 .srp-SUV { 8050 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/suv.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8051 } 8052 8053 .srp-Van { 8054 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/van.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8055 } 8056 8057 .srp-Truck { 8058 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/truck.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8059 } 8060 8061 .srp-Hatchback { 8062 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/hatch.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8063 } 8064 8065 .srp-Wagon { 8066 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/wagon.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8067 } 8068 8069 .srp-Coupe { 8070 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/coupe.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8071 } 8072 8073 .srp-Sedan { 8074 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/sedan.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8075 } 8076 8077 .srp-Convertible { 8078 background: url(https://bucket.dealervenom.com/assets/oem/toyota/filters/convertible.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=120&height=100); 8079 } 8080 8081 .srp-Crossover { 8082 background : url(https://bucket.dealervenom.com/assets/oem/toyota/filters/crossover.png?auto=compress%2Cformat&ixlib=php-1.2.1&width=140); 8083 } 8084 8085 .vehicle-special { 8086 background-color: #f00f00 !important; 8087 } 8088 8089 8090 .srp-header { 8091 top: 75px; 8092 } 8093 8094 .car-title > p { 8095 color: #eb0a1e; 8096 } 8097 8098 .listing-bottom-row { 8099 background-color: #000000; 8100 color: #ffffff; 8101 } 8102 8103 .specs { 8104 height: 40px; 8105 } 8106 8107 .img-container { 8108 padding-bottom: 75%; 8109 } 8110 8111 #clearSearchResults button { 8112 color: #eb0a1e; 8113 } 8114 8115 .srp-windowsticker.srp_cta:hover { 8116 background-color: #ffffff; 8117 color: #eb0a1e; 8118 border-color: #eb0a1e; 8119 } 8120 8121 .reserved-vehicle { 8122 background-color: #EB0A11; 8123 color: ; 8124 } 8125 8126 8127 .vehicle-price-container { 8128 height: 150px; 8129 } 8130 8131 @media screen and (max-width: 1024px) 8132 { 8133 .srp-header { 8134 top: 75px; 8135 height: auto; 8136 flex-flow: column nowrap; 8137 padding: 25px; 8138 box-sizing: border-box; 8139 } 8140 8141 .srp-search { 8142 position: relative; 8143 } 8144 #clearSearchResults { 8145 position: absolute; 8146 right: 10px; 8147 background: #fff; 8148 } 8149 #clearSearchResults button { 8150 padding-right: 0; 8151 } 8152 .mobileFilters { 8153 bottom: 0 8154 } 8155 8156 .dv-logged-in .srp-filters { 8157 padding-top: 75px 8158 } 8159 } 8160 8161 .filterResultCount { 8162 display: none 8163 } 8164 @media screen and (max-width: 1024px){ 8165 .filterResultCount { 8166 background-color: #EB0A1E; 8167 color: #FFFFFF; 8168 display: none; 8169 position: fixed; 8170 bottom: 0; 8171 z-index: 2147483647; 8172 width: 100%; 8173 text-align: center; 8174 padding: 12.5px 0; 8175 } 8176 .filterResultCount:hover { 8177 cursor: pointer; 8178 } 8179 .filterResultCount.filter-result-count-active { 8180 display: block 8181 } 8182 } 8183 .dv-srp-search-options { 8184 display: none; 8185 position: relative; 8186 box-sizing: border-box 8187 } 8188 8189 .dv-srp-search-options * { 8190 box-sizing: border-box 8191 } 8192 8193 .sortFilters .dv-srp-sort-mobile { 8194 position: absolute; 8195 width: 100%; 8196 min-width: 160px; 8197 left: 0; 8198 top: 100%; 8199 padding: 0; 8200 background: #fff; 8201 box-shadow: 0 8px 16px 0 rgba(0,0,0,.2); 8202 z-index: 1; 8203 text-align: left; 8204 overflow: hidden; 8205 visibility: hidden; 8206 opacity: 0; 8207 height: 0 8208 } 8209 8210 .sortFilters .dv-srp-sort-desktop { 8211 position: absolute; 8212 width: 100%; 8213 min-width: 160px; 8214 left: 0; 8215 top: 80%; 8216 padding: 0; 8217 background: #fff; 8218 box-shadow: 0 8px 16px 0 rgba(0,0,0,.2); 8219 z-index: 1; 8220 text-align: left; 8221 overflow: hidden; 8222 visibility: hidden; 8223 opacity: 0; 8224 height: 0 8225 } 8226 8227 .sortFilters .dv-srp-sort-mobile.dv-srp-sort-mobile-active, 8228 .sortFilters .dv-srp-sort-desktop.dv-srp-sort-desktop-active { 8229 overflow: auto; 8230 visibility: visible; 8231 opacity: 1; 8232 height: fit-content; 8233 padding: 12.5px 8234 } 8235 8236 .sortFilters .dv-srp-sort-mobile a,
8237 .sortFilters .dv-srp-sort-desktop a { 8238 font-size: 12px; 8239 display: block; 8240 margin: 12.5px 0; 8241 color: #000; 8242 display: flex; 8243 display: -webkit-flex; 8244 display: -ms-flexbox; 8245 justify-content: flex-start; 8246 align-items: center; 8247 gap: 6.25px; 8248 text-transform: capitalize 8249 } 8250 8251 .sortFilters .dv-srp-sort-mobile a:hover, 8252 .sortFilters .dv-srp-sort-desktop a:hover { 8253 cursor: pointer; 8254 } 8255 8256 .sortFilters .dv-srp-sort-mobile a.dv-srp-sort-selected, 8257 .sortFilters .dv-srp-sort-desktop a.dv-srp-sort-selected { 8258 color: var(--primary-color) 8259 } 8260 8261 .sortFilters .dv-srp-sort-mobile a i, 8262 .sortFilters .dv-srp-sort-desktop a i { 8263 display: block; 8264 color: var(--primary-color); 8265 width: 15px; 8266 text-align: center 8267 } 8268 8269 #sortByDesktop { 8270 position: relative; 8271 box-sizing: border-box; 8272 margin-right: 25px 8273 } 8274 8275 #sortByDesktop * { 8276 box-sizing: border-box; 8277 } 8278 8279 @media screen and (min-width: 1024px) { 8280 .dv-srp-search-options-wrapper { 8281 /* background: var(--primary-color); */ 8282 color: #505050; 8283 padding: 12.5px; 8284 min-width: 100%; 8285 white-space: nowrap; 8286 } 8287 8288 .dv-srp-search-options-wrapper:hover { 8289 cursor: pointer; 8290 } 8291 8292 .dv-srp-search-options-wrapper .dv-srp-search-options-label { 8293 display: inline-block; 8294 vertical-align: bottom; 8295 font-size: 14px; 8296 font-weight: 600 8297 } 8298 8299 .dv-srp-search-options-wrapper .dv-srp-search-options-label i { 8300 margin-right: 6.25px 8301 } 8302 } 8303 8304 @media screen and (max-width: 1024px) { 8305 .srp-header { 8306 background: #f8f8f8; 8307 } 8308 .srp-header .dv-srp-search-options { 8309 display: flex; 8310 display: -webkit-flex; 8311 display: -ms-flexbox; 8312 margin-top: 12.5px; 8313 gap: 25px; 8314 } 8315 .srp-header .dv-srp-search-options .sortFilters, 8316 .srp-header .dv-srp-search-options .showFiltersNonLegacy, 8317 .srp-header .dv-srp-search-options .saveFilters { 8318 width: 33.333%; 8319 flex: 1 1 33.333%; 8320 background: var(--primary-color); 8321 color: #fff; 8322 padding: 6.25px; 8323 display: flex; 8324 display: -webkit-flex; 8325 display: -ms-flexbox; 8326 text-align: center; 8327 justify-content: center; 8328 align-items: center; 8329 font-size: 12px; 8330 text-transform: uppercase; 8331 } 8332 .srp-header .dv-srp-search-options .sortFilters:hover, 8333 .srp-header .dv-srp-search-options .showFiltersNonLegacy:hover, 8334 .srp-header .dv-srp-search-options .saveFilters:hover { 8335 cursor: pointer; 8336 } 8337 .srp-header .dv-srp-search-options .saveFilters { 8338 display: none !important 8339 } 8340 .srp-searchbar { 8341 background: #fff; 8342 flex-basis: 100%; 8343 border: 1px solid #e9e9e9; 8344 } 8345 .srp-searchbar input { 8346 background-color: #fff !important; 8347 } 8348 .srp-searchbar > .fa-search { 8349 padding: 0 12.5px; 8350 } 8351 #searchbox { 8352 width: 100%; 8353 } 8354 } 8355 @media screen and (max-width: 480px) { 8356 .srp-header .dv-srp-search-options { 8357 gap: 12.5px; 8358 } 8359 .srp-header .dv-srp-search-options .sortFilters, 8360 .srp-header .dv-srp-search-options .showFiltersNonLegacy, 8361 .srp-header .dv-srp-search-options .saveFilters { 8362 font-size: 10px 8363 } 8364 } 8365 8366 .ag-srp-miles { 8367 background: #eee; 8368 border-radius: 15px; 8369 font-weight: 500; 8370 display:block; 8371 padding:4px; 8372 color:#000; 8373 line-height:16px; 8374 font-size:12px !important; 8375} 8376 8377.srp-bottom-disclaimers { 8378 font-size: 12px; 8379 color: #bcc4cc; 8380} 8381.srp-bottom-disclaimers h4 { 8382 text-transform: none; 8383 padding-bottom: 12.5px; 8384 color: #000; 8385} 8386/*Pricing Slash*/ 8387.dv-price-stack p { 8388 position: relative; 8389} 8390.dv-price-stack .dv-price-slash { 8391 z-index: 98; 8392 position: absolute; 8393 right: 0; 8394 max-width: 50px; 8395} 8396/*Pricing Slash*/ 8397 8398/*Vin-Stock Container styles*/ 8399 .srp-extra-div { 8400 display: flex; 8401 margin: auto; 8402 padding-bottom: 5px; 8403 padding-bottom: 12.5px !important; 8404 padding-top: 12.5px !important; 8405 } 8406 .srp-cta a:last-of-type { 8407 margin-bottom: 0px !important; 8408} 8409/*Vin-Stock Container styles*/</style> 8410<!-- Modals --> 8411<!-- Twilio Modal --> 8412 8413<!-- Youtube Player Modal --> 8414<div class="modal fade" tabindex="-1" role="dialog" id="youtube_modal"> 8415 <div class="modal-dialog youtube-embed" role="document"> 8416 <div class="modal-content youtube-embed"> 8417 <div class="modal-body youtube-modal-body"> 8418 <div id="ytplayer"></div> 8419 </div> 8420 </div><!-- /.modal-content --> 8421 </div><!-- /.modal-dialog --> 8422</div><!-- /.modal --> 8423 8424<!-- compare Player Modal --> 8425<div class="modal fade" tabindex="-1" role="dialog" id="compare_modal"> 8426 <div class="modal-dialog compare-embed" role="document"> 8427 <div class="modal-content compare-embed"> 8428 <div class="modal-body compare-modal-body"> 8429 <div id="ytplayer"></div> 8430 </div> 8431 </div><!-- /.modal-content --> 8432 </div><!-- /.modal-dialog --> 8433</div><!-- /.modal --> 8434 8435<div class="modal fade" tabindex="-1" role="dialog" id="custom_modal" style="padding: 20px"> 8436 <div class="modal-dialog custom-embed" role="document"> 8437 <div class="modal-content custom-embed"> 8438 <div class="modal-body custom-modal-body"> 8439 <div id="custom_player"></div> 8440 </div> 8441 </div><!-- /.modal-content --> 8442 </div><!-- /.modal-dialog --> 8443</div><!-- /.modal --> 8444 8445<div class="cd-panel cd-panel--from-right js-cd-panel-main"> 8446 <section class="cd-panel__header"> 8447 <p id="popup_left_title"></p> 8448 <a href="javascript:void(0);" class="cd-panel__close js-cd-close">Close</a> 8449 </section> 8450 <div class="cd-panel__container"> 8451 <div class="cd-panel__subheader"> 8452 <div class="cd-panel__subheader-left"> 8453 <h4 id="popup_left_vehicle_title"></h4> 8454 <p>Stock: <span id="popup_left_stock_number"></span> <span>|</span> Vin: <span id="popup_left_vin"></span></p> 8455 </div> 8456 </div> 8457 <div class="cd-panel__content"> 8458 <div class="forms_container"> 8459 <div class="popup_form" id="srp_form_container" style="display: none;"> 8460 </div> 8461 8462 <div id="payment_calculator_container" style="display: none;"> 8463 <style> 8464 .dv-payment-calculator { 8465 max-width: 1428.75px; 8466 margin: 0 auto; 8467 font-family: inherit; 8468 background: #fff; 8469 } 8470 .dv-payment-calculator .dv-calculator-disclaimer { 8471 padding: 25px; 8472 font-size: 14px; 8473 color: #879099; 8474 } 8475 @media screen and (max-width: 768px) { 8476 .dv-payment-calculator { 8477 padding: 25px; 8478 } 8479 } 8480 .dv-payment-calculator h2 { 8481 font-size: 24px; 8482 font-weight: bold; 8483 padding: 25px 50px 8484 } 8485 .dv-payment-calculator * { 8486 box-sizing: border-box; 8487 } 8488 .dv-payment-calculator .dv-payment-calculator-container { 8489 display: block; 8490 } 8491 .dv-payment-calculator .dv-payment-calculator-container .dv-payment-calculator-calc { 8492 background: #fff; 8493 padding: 0 50px; 8494 } 8495 @media screen and (max-width: 768px) { 8496 .dv-payment-calculator .dv-payment-calculator-container .dv-payment-calculator-calc { 8497 margin-bottom: 50px; 8498 } 8499 } 8500 .dv-payment-calculator .dv-payment-calculator-container .dv-payment-calculator-col { 8501 width: 100%; 8502 } 8503 .dv-payment-calculator .dv-payment-calculator-wrapper { 8504 display: -webkit-box; 8505 display: flex; 8506 width: 100%; 8507 } 8508 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-wrapper { 8509 padding: 0 50px; 8510 } 8511 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-12 { 8512 width: 100%; 8513 -webkit-box-flex: 1; 8514 flex: 1 1 100%; 8515 } 8516 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-8 { 8517 width: 66.66666667%; 8518 -webkit-box-flex: 1; 8519 flex: 1 1 66.66666667%; 8520 } 8521 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-6 { 8522 margin: 0px 25px 0 0; 8523 width: calc(1 / 2 * 100% - (1 - 1 / 2) * 25px); 8524 -webkit-box-flex: 1; 8525 flex: 1 1 calc(1 / 2 * 100% - (1 - 1 / 2) * 25px); 8526 } 8527 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-6:nth-child(2n) { 8528 margin-right: 0; 8529 } 8530 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-4 {
8531 width: 33.33333%; 8532 -webkit-box-flex: 1; 8533 flex: 1 1 33.33333%; 8534 } 8535 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-3 { 8536 width: 25%; 8537 -webkit-box-flex: 1; 8538 flex: 1 1 25%; 8539 margin: 0 25px; 8540 } 8541 .dv-payment-calculator .dv-payment-calculator-input-group { 8542 position: relative; 8543 margin: 25px 0; 8544 } 8545 .dv-payment-calculator .dv-payment-calculator-input-group label { 8546 display: block; 8547 padding: 0 0 10px 0; 8548 font-size: 16px; 8549 color: #879099; 8550 font-weight: 500; 8551 width: 100%; 8552 } 8553 .dv-payment-calculator .dv-payment-calculator-input-group label #dv-payment-calculator-range-value { 8554 display: block; 8555 float: right; 8556 margin: 0; 8557 } 8558 .dv-payment-calculator .dv-payment-calculator-input-group .dv-payment-calculator-range-list { 8559 display: -webkit-box; 8560 display: flex; 8561 width: 100%; 8562 -webkit-box-pack: justify; 8563 justify-content: space-between; 8564 margin-top: 0px; 8565 padding-top: 0px; 8566 } 8567 .dv-payment-calculator .dv-payment-calculator-input-group .dv-payment-calculator-range-list option { 8568 width: 3ex; 8569 display: -webkit-box; 8570 display: flex; 8571 -webkit-box-pack: center; 8572 justify-content: center; 8573 height: 42px; 8574 -webkit-box-align: end; 8575 align-items: end; 8576 height: 4ex; 8577 } 8578 .dv-payment-calculator .dv-payment-calculator-input-group .dv-payment-calculator-range-list option:before { 8579 content: attr(value); 8580 font-size: 12px; 8581 color: rgba(0,0,0,0.32); 8582 display: block; 8583 } 8584 .dv-payment-calculator .dv-payment-calculator-input-group input { 8585 border: none; 8586 border-bottom: 1px solid #e1e6eb; 8587 padding-left: 15px; 8588 color: #879099; 8589 padding: 5px 5px 5px 25px; 8590 font-size: 14px; 8591 font-family: inherit; 8592 outline: none; 8593 line-height: 1; 8594 width: 100%; 8595 } 8596 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range] { 8597 padding: 10px 0 0 0; 8598 border-bottom: 0; 8599 -webkit-appearance: none; 8600 -moz-appearance: none; 8601 margin: 10px 0 0 0; 8602 width: 100%; 8603 } 8604 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]:focus { 8605 outline: none; 8606 } 8607 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]:focus::-webkit-slider-runnable-track { 8608 background: #2fd566; 8609 } 8610 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]:focus::-ms-fill-lower { 8611 background: #2fd566; 8612 } 8613 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]:focus::-ms-fill-upper { 8614 background: #2fd566; 8615 } 8616 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-webkit-slider-runnable-track { 8617 width: 100%; 8618 height: 5px; 8619 cursor: pointer; 8620 animate: 0.2s; 8621 box-shadow: 0px 0px 0px #000; 8622 background: #2fd566; 8623 border-radius: 1px; 8624 border: 0px solid #000; 8625 } 8626 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-webkit-slider-thumb { 8627 box-shadow: 0px 0px 0px #000; 8628 border: 1px solid #171a1d; 8629 height: 18px; 8630 width: 18px; 8631 border-radius: 25px; 8632 background: #fff; 8633 cursor: pointer; 8634 -webkit-appearance: none; 8635 margin-top: -7px; 8636 } 8637 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-moz-range-track { 8638 width: 100%; 8639 height: 5px; 8640 cursor: pointer; 8641 animate: 0.2s; 8642 box-shadow: 0px 0px 0px #000; 8643 background: #2fd566; 8644 border-radius: 1px; 8645 border: 0px solid #000; 8646 } 8647 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-moz-range-thumb { 8648 box-shadow: 0px 0px 0px #000; 8649 border: 1px solid #171a1d; 8650 height: 18px; 8651 width: 18px; 8652 border-radius: 25px; 8653 background: #fff; 8654 cursor: pointer; 8655 } 8656 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-ms-track { 8657 width: 100%; 8658 height: 5px; 8659 cursor: pointer; 8660 animate: 0.2s; 8661 background: transparent; 8662 border-color: transparent; 8663 color: transparent; 8664 } 8665 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-ms-fill-lower { 8666 background: #2fd566; 8667 border: 0px solid #000; 8668 border-radius: 2px; 8669 box-shadow: 0px 0px 0px #000; 8670 } 8671 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-ms-fill-upper { 8672 background: #2fd566; 8673 border: 0px solid #000; 8674 border-radius: 2px; 8675 box-shadow: 0px 0px 0px #000; 8676 } 8677 .dv-payment-calculator .dv-payment-calculator-input-group input[type=range]::-ms-thumb {
8678 margin-top: 1px; 8679 box-shadow: 0px 0px 0px #000; 8680 border: 1px solid #171a1d; 8681 height: 18px; 8682 width: 18px; 8683 border-radius: 25px; 8684 background: #fff; 8685 cursor: pointer; 8686 } 8687 .dv-payment-calculator .dv-payment-calculator-input-group span { 8688 position: absolute; 8689 left: 0; 8690 bottom: 11px; 8691 color: #879099; 8692 font-size: 14px; 8693 line-height: 1; 8694 } 8695 .dv-payment-calculator .dv-payment-calculator-results { 8696 background: #141518; 8697 padding-bottom: 25px; 8698 } 8699 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-results-header { 8700 padding: 25px 50px; 8701 } 8702 .dv-payment-calculator .dv-payment-calculator-results p { 8703 font-size: 18px; 8704 color: #fff; 8705 margin: 0; 8706 } 8707 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-col-3 { 8708 margin: 0; 8709 } 8710 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-input-group { 8711 margin-top: 0; 8712 margin-bottom: 0; 8713 } 8714 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-input-group label { 8715 font-size: 10px; 8716 font-weight: bold; 8717 padding-bottom: 5px; 8718 } 8719 .dv-payment-calculator .dv-payment-calculator-results .dv-payment-calculator-input-group p { 8720 background: transparent; 8721 color: #fff; 8722 border-bottom: none; 8723 font-size: 20px; 8724 font-weight: 600; 8725 letter-spacing: 1px; 8726 font-family: inherit; 8727 margin: 0; 8728 } 8729 @media screen and (max-width: 768px) { 8730 .dv-payment-calculator .dv-payment-calculator-wrapper { 8731 display: block; 8732 } 8733 .dv-payment-calculator .dv-payment-calculator-wrapper [class*='dv-payment-calculator-col'] { 8734 width: 100%; 8735 -webkit-box-flex: 1; 8736 flex: 1 1 100%; 8737 } 8738 } 8739 @media screen and (max-width: 768px) { 8740 .dv-payment-calculator .dv-payment-calculator-wrapper { 8741 font-size: 0; 8742 } 8743 .dv-payment-calculator .dv-payment-calculator-wrapper .dv-payment-calculator-col-3 { 8744 font-size: 0; 8745 display: inline-block; 8746 width: 50%; 8747 } 8748 .dv-payment-calculator .dv-payment-calculator-wrapper [class*='dv-payment-calculator-col'] { 8749 margin-bottom: 25px; 8750 } 8751 .dv-payment-calculator .dv-payment-calculator-wrapper [class*='dv-payment-calculator-col']:last-child { 8752 margin-bottom: 0; 8753 } 8754 } 8755 8756 </style> 8757 8758 <div class="dv-payment-calculator"> 8759 <div class="dv-payment-calculator-container"> 8760 <div class="dv-payment-calculator-col"> 8761 <h2>Payment Calculator</h2> 8762 <div class="dv-payment-calculator-calc"> 8763 <div class="dv-payment-calculator-wrapper"> 8764 <div class="dv-payment-calculator-col-6"> 8765 <div class="dv-payment-calculator-input-group"> 8766 <label for="Purchase Price">Purchase Price</label>
8767 <span>$</span> 8768 <input type="text" value="0" id="carPrice" placeholder="0" onChange="calculate()" tabindex="2" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8769 </div> 8770 <div class="dv-payment-calculator-input-group"> 8771 <label for="Tax Rate">Tax Rate</label> 8772 <span>%</span> 8773 <input type="text" id="taxRate" value="3" placeholder="0" onChange="calculate()" tabindex="4" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8774 </div> 8775 <div class="dv-payment-calculator-input-group"> 8776 <label for="APR">APR</label> 8777 <span>%</span> 8778 <input type="text" value="5.99" id="intRate" placeholder="0" onChange="calculate()" tabindex="6" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8779 </div> 8780 </div> 8781 <div class="dv-payment-calculator-col-6"> 8782 <div class="dv-payment-calculator-input-group"> 8783 <label for="Trade-in Value">Trade-in Value</label> 8784 <span>$</span> 8785 <input type="text" value="0" id="tradeValue" placeholder="0" onChange="calculate()" tabindex="3" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8786 </div> 8787 <div class="dv-payment-calculator-input-group"> 8788 <label for="Trade-in Payoff Amount">Trade-in Payoff Amount</label> 8789 <span>$</span> 8790 <input type="text" value="0" id="tradePayoff" placeholder="0" onChange="calculate()" tabindex="4" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8791 </div> 8792 <div class="dv-payment-calculator-input-group"> 8793 <label for="Down Payment">Down Payment</label> 8794 <span>$</span> 8795 <input type="text" value="0" id="downPay" placeholder="0" onChange="calculate()" tabindex="5" onkeypress="return (event.charCode !=8 && event.charCode ==0 || ( event.charCode == 46 || (event.charCode >= 48 && event.charCode <= 57)))"> 8796 </div> 8797 </div> 8798 </div> 8799 <div class="dv-payment-calculator-input-group"> 8800 <label for="Loan Term">Loan Term <p id="dv-payment-calculator-range-value"></p></label> 8801 <input type="range" value="72" step="12" min="12" max="84" list="dv-range-list-options" id="termRate" class="dv-payment-calculator-range-input" onChange="calculate()" tabindex="7"> 8802 8803 <datalist class="dv-payment-calculator-range-list" id="dv-range-list-options"> 8804 <option value="12"> </option> 8805 <option value="24"> </option> 8806 <option value="36"> </option> 8807 <option value="48"> </option> 8808 <option value="60"> </option> 8809 <option value="72"> </option> 8810 <option value="84"> </option> 8811 </datalist> 8812 </div> 8813 </div> 8814 </div> 8815 <div class="dv-payment-calculator-col"> 8816 <div class="dv-payment-calculator-results"> 8817 <div class="dv-payment-calculator-results-header"> 8818 <p>Payment Options</p> 8819 </div> 8820 <div class="dv-payment-calculator-wrapper"> 8821 <div class="dv-payment-calculator-col-3"> 8822 <div class="dv-payment-calculator-input-group"> 8823 <label for="Monthly Payment">Monthly Payment</label> 8824 <p id="result">$0.00</p> 8825 </div> 8826 </div> 8827 <div class="dv-payment-calculator-col-3"> 8828 <div class="dv-payment-calculator-input-group"> 8829 <label for="Bi-Weekly Payment">Bi-Weekly Payment</label> 8830 <p id="result0">$0.00</p> 8831 </div> 8832 </div> 8833 <div class="dv-payment-calculator-col-3"> 8834 <div class="dv-payment-calculator-input-group"> 8835 <label for="Weekly Payment">Weekly Payment</label> 8836 <p id="result2">$0.00</p> 8837 </div> 8838 </div> 8839 <div class="dv-payment-calculator-col-3"> 8840 <div class="dv-payment-calculator-input-group"> 8841 <label for="Total Amount Financed">Total Amount Financed</label> 8842 <p id="principal">$0.00</p> 8843 </div> 8844 </div> 8845 </div> 8846 <div class="dv-payment-calculator-wrapper"> 8847 <div class="dv-payment-calculator-col-3"> 8848 <div class="dv-payment-calculator-input-group"> 8849 <label for="Total Amount Down">Total Amount Down</label> 8850 <p id="totalAmountDown">$0.00</p> 8851 </div> 8852 </div> 8853 </div> 8854 </div> 8855 </div> 8856 </div> 8857 <div class="dv-calculator-disclaimer"> 8858 <p>*Calculated payments are estimated. Title and other fees and incentives may not be included in this calculation, which is an estimate only. Monthly payment estimates are for informational purpose and do not represent a financing offer from the seller of this vehicle. Other taxes may apply. Please complete a finance application for rates that you qual
8858ify for.</p> 8859 </div> 8860 </div> 8861
8861<script> 8862 $(function () { 8863 // Term Range Selector 8864 var PaymentCalcRange = function () { 8865 var SliderValueHTML = $("#dv-payment-calculator-range-value"); 8866 var Slider = $(".dv-payment-calculator-range-input"); 8867 SliderValueHTML.html(Slider.val() + " mo"); 8868 $(document).on("input", ".dv-payment-calculator-range-input", function () { 8869 SliderValueHTML.html($(this).val() + " mo"); 8870 }); 8871 }; 8872 PaymentCalcRange(); 8873 calculate(); 8874 }); 8875 8876 function calculate() { 8877 //Get the values of all of elements, convert the strings into ints, create decimals for values that are percentages. 8878 var carPrice = parseFloat( 8879 document.getElementById("carPrice").value.replace(/\$|,/g, "") 8880 ) || 0; 8881 var taxRate = (parseFloat(document.getElementById("taxRate").value) || 0) / 100; 8882 var tradeValue = parseFloat( 8883 document.getElementById("tradeValue").value.replace(/\$|,/g, "") 8884 ) || 0; 8885 var tradePayoff = parseFloat( 8886 document.getElementById("tradePayoff").value.replace(/\$|,/g, "") 8887 ) || 0; 8888 var downPay = parseFloat( 8889 document.getElementById("downPay").value.replace(/\$|,/g, "") 8890 ) || 0; 8891 var intRate = parseFloat(document.getElementById("intRate").value) || 0; 8892 var termRate = parseFloat(document.getElementById("termRate").value); 8893 8894 //Calculate the principal 8895 // Trade-in equity offsets the down payment; the combined amount is subtracted once. 8896 var taxAmount = carPrice * taxRate; 8897 var carWithTax = carPrice + taxAmount; 8898 var tradeEquity = parseFloat((tradeValue - tradePayoff).toFixed(2)); 8899 var totalAmountDown = parseFloat((downPay + tradeEquity).toFixed(2)); 8900 var carPrincipal = (carWithTax - totalAmountDown).toFixed(2); 8901 var intMonth = (intRate/100) / 12; 8902 8903 // Calculate Monthly/Bi-Weekly/Weekly Payments 8904 var monthly = 8905 intMonth === 0 8906 ? parseInt(carPrincipal / termRate).toFixed(2) 8907 : interest(carPrincipal, intMonth, termRate); 8908 var biWeekly = parseFloat(monthly / 2).toFixed(2); 8909 var weekly = parseFloat(monthly / 4).toFixed(2); 8910 8911 //Update the principal element with the new value. 8912 var carPrincipalFormatted = carPrincipal < 0 8913 ? "-$" + numberWithCommas(Math.abs(carPrincipal).toFixed(2).toString()) 8914 : "$" + numberWithCommas(carPrincipal.toString()); 8915 document.getElementById("principal").innerHTML = carPrincipalFormatted; 8916 8917 //Set the final calculated payment to the result element. 8918 document.getElementById("result").innerHTML = "$" + monthly; 8919 document.getElementById("result0").innerHTML = "$" + biWeekly; 8920 document.getElementById("result2").innerHTML = "$" + weekly; 8921 8922 var totalAmountDownFormatted = totalAmountDown < 0 8923 ? "-$" + numberWithCommas(Math.abs(totalAmountDown).toFixed(2).toString()) 8924 : "$" + numberWithCommas(totalAmountDown.toFixed(2).toString()); 8925 document.getElementById("totalAmountDown").innerHTML = totalAmountDownFormatted; 8926 } 8927 8928 function numberWithCommas(x) { 8929 return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 8930 } 8931 8932 function interest(principal, intRate, term) { 8933 var int1 = 1 + intRate; 8934 var intEx = int1 * int1; 8935 for (var i = 0; i < term - 2; i++) { 8936 intEx = intEx * int1; 8937 } 8938 var intEx1 = intEx - 1; 8939 var intEx2 = intRate / intEx1; 8940 var intEx3 = intEx2 + intRate; 8941 var pay = intEx3 * principal; 8942 return pay.toFixed(2); 8943 } 8944 8945 </script>
8945 8946 </div> 8947 </div> 8948 </div> <!-- cd-panel__content --> 8949 </div> <!-- cd-panel__container --> 8950 <div class="cd-panel__otherside"> 8951 </div> 8952</div> <!-- cd-panel --> 8953 <footer> 8954 <!-- sub-footer --> 8955<div class="row"> 8956 <div class="footer_top" 8957 style="background: linear-gradient(rgba(0,0,0,0.7), rgba(0,0,0,0.7)), url(); background-position:center center; background-size: cover;"> 8958 <div class="footer_container"> 8959 <div class="row footer-links"> 8960 8961 <div class="foot3 footer-soc-icons footer-bar1"> 8962 <div id="footer-sidebar1"> 8963 <h5>Stay Connected</h5> 8964<a href="https://www.facebook.com/HubertVesterToyota/" target='_blank'><i class="fab fa-facebook fa-2x" style="color:#3C5A99;"></i></a> 8965<a href="https://x.com/HVToyota" target='_blank'><i class="fa-brands fa-x-twitter fa-2x" style="color:#FFF;"></i></a> 8966<a href="https://www.instagram.com/hvtoyota_wilsonnc/" target='_blank'><i class="fab fa-instagram fa-2x" style="color:#C13584;"></i></a> 8967<!--<a href="" target='_blank'><i class="fab fa-youtube fa-2x" style="color:#FF0000;"></i></a>--> 8968 8969<!--<h5>Stay Connected</h5> 8970<a href="/facebook/" data-lity><i class="fab fa-facebook-f fa-2x" style="color:#3C5A99;"></i></a> 8971<a href="/twitter/" data-lity><i class="fab fa-twitter fa-2x" style="color:#1DA1F2;"></i></a> 8972<a href="/instagram/" data-lity><i class="fab fa-instagram fa-2x" style="color:#C13584;"></i></a> 8973<a href="/youtube/" data-lity><i class="fab fa-youtube fa-2x" style="color:#FF0000;"></i></a>--> </div> 8974 </div> 8975 8976 <div class="foot3 footer-middle-sec"> 8977 <div id="footer-sidebar2"> 8978 <h5>Call Us</h5> 8979<a data-ag-event="clickToCall" data-ag-event-set-prop="clickToCallDepartment|Sales" href="tel:252.293.6513" class="telephone">252.293.6513</a> 8980<div> 8981<h5>Get Directions</h5> 8982<a data-ag-event="getDirections" target="_blank" href="https://maps.app.goo.gl/3y3jqzq82XTNvT8q7"><span class='dealer-full-address'><span>3712 Raleigh Rd Pkwy W </span><span> </span><span></span><span>Wilson, </span><span>NC </span><span>27896 </span></span></a> 8983</div> </div> 8984 </div> 8985 8986 <div class="foot3 quicklinks"> 8987 <h5>Quick Links</h5> 8988 <div id="footer-sidebar3"> 8989 <aside id="nav_menu-2" class="widget widget_nav_menu"><div class="menu-quick-links-container"><ul id="menu-quick-links" class="menu"><li id="menu-item-76742" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-home menu-item-76742"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/" class="menu-image-title-after"><span class="menu-image-title">Home</span></a></li> 8990<li id="menu-item-76763" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-76763"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="/service/" class="menu-image-title-after"><span class="menu-image-title">Service Center</span></a></li> 8991<li id="menu-item-76762" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-76762"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/about/" class="menu-image-title-after"><span class="menu-image-title">About Us</span></a></li> 8992<li id="menu-item-76743" class="menu-item menu-item-type-post_type menu-item-object-page current-menu-item page_item page-item-16 current_page_item menu-item-76743"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/new-vehicles/" class="menu-image-title-after"><span class="menu-image-title">New Vehicles</span></a></li> 8993<li id="menu-item-77296" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-77296"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/service/schedule-service/" class="menu-image-title-after"><span class="menu-image-title">Schedule Service</span></a></li> 8994<li id="menu-item-76746" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-76746"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/contact/" class="menu-image-title-after"><span class="menu-image-title">Contact Us</span></a></li> 8995<li id="menu-item-77297" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-77297"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="/new-vehicles/?flags.type=Special" class="menu-image-title-after"><span class="menu-image-title">New Vehicle Specials</span></a></li> 8996<li id="menu-item-76747" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-76747"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/finance/" class="menu-image-title-after"><span class="menu-image-title">Finance Center</span></a></li> 8997<li id="menu-item-77299" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-77299"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/hours-and-directions/" class="menu-image-title-after"><span class="menu-image-title">Hours & Directions</span></a></li> 8998<li id="menu-item-76744" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-76744"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/used-vehicles/" class="menu-image-title-after"><span class="menu-image-title">Pre-Owned Vehicles</span></a></li> 8999<li id="menu-item-77298" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-77298"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/finance/finance-application/" class="menu-image-title-after"><span class="menu-image-title">Finance Application</span></a></li> 9000<li id="menu-item-76765" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-76765"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="/value-trade/" class="menu-image-title-after"><span class="menu-image-title">Value Your Trade</span></a></li> 9001<li id="menu-item-76761" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-76761"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="/used-vehicles/?flags.type=Certified" class="menu-image-title-after"><span class="menu-image-title">Certified Pre-Owned Inventory</span></a></li> 9002<li id="menu-item-76764" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-76764"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="/parts/" class="menu-image-title-after"><span class="menu-image-title">Parts Center</span></a></li> 9003<li id="menu-item-76748" class="menu-item menu-item-type-post_type menu-item-object-page menu-item-privacy-policy menu-item-76748"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" href="https://www.hubertvestertoyota.com/privacy-policy/" class="menu-image-title-after"><span class="menu-image-title">Privacy Policy</span></a></li> 9004<li id="menu-item-76766" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-76766"><a data-ag-event="menu_interaction" style="" data-element_type="new-vehicles" target="_blank" href="https://www.toyota.com/recall/" class="menu-image-title-after"><span class="menu-image-title">Safety Recalls & Service Campaigns</span></a></li> 9005</ul></div></aside> </div> 9006 </div> 9007 </div> 9008 9009 <div class="row"> 9010 <div class="footer_bottom-light" 9011 > 9012 <div class="footer-powered-container"> 9013 <div class="footer-copyright"> 9014 <h6><p>© 2026 Hubert Vester Toyota. </p> 9015 <a href="/sitemap.xml">Sitemap</a> <p>|</p> 9016 <a href="/privacy-policy/">Privacy Policy</a> 9017 </h6> 9018 </div> 9019 <div class="footer-powered"> 9020 <h6> 9021 <p>Advanced Automotive Websites By</p> 9022 <a href="https://dealeralchemist.com" target="_blank"> 9023 <h6>Dealer Alchemist</h6> 9024 </a> 9025 </h6> 9026 </div> 9027 </div> 9028 </div> 9029 </div> 9030 </div> 9031 </div> 9032</div> 9033 9034<style>table.mabel-bhi-businesshours tr.mbhi-is-current {
9035background: #E9E9E9; 9036}</style><!-- DV Google Tag Manager (noscript) -->
vendor: 68 bytes, lines 9036-9037
9036 9037<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=
9037GTM-5CPFDTJM
vendor: 91 bytes, lines 9037-9038
9037" height="0" width="0" 9038 style="display:none;visibility:hidden"></iframe></noscript>
9039<!-- DV End Google Tag Manager (noscript) --> 9040
9041<script type='text/javascript' src='https://www.hubertvestertoyota.com/wp/wp-includes/js/jquery/jquery.min.js?ver=3.6.0' id='jquery-core-js'></script>
vendor: 1 bytes, line 9041
9041
9042<script type='text/javascript' id='wp-api-request-js-extra'> 9043/* <![CDATA[ */ 9044var wpApiSettings = {"root":"https:\/\/www.hubertvestertoyota.com\/wp-json\/","nonce":"7d48aea91d","versionString":"wp\/v2\/"}; 9045/* ]]> */ 9046</script>
vendor: 1 bytes, line 9046
9046
9047<script type='text/javascript' src='https://www.hubertvestertoyota.com/wp/wp-includes/js/api-request.min.js?ver=5.9.5' id='wp-api-request-js'></script>
vendor: 1 bytes, line 9047
9047
9048<script type='text/javascript' id='mabel-business-hours-indicator-pro-js-extra'> 9049/* <![CDATA[ */ 9050var mabel_script_vars = {"ajaxurl":"https:\/\/www.hubertvestertoyota.com\/wp\/wp-admin\/admin-ajax.php","locations":[{"Name":"Parts","Timezone":"America\/New_York","Type":"AutoPartsStore","Days":[{"Day":"Monday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Tuesday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Wednesday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Thursday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Friday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Saturday","Hours":[{"From":"8:00","To":"1:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Sunday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]}],"Holidays":[{"Day":"4","Month":"Jul","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}],"Name":"4th of July"}],"Vacations":[],"Image":""},{"Name":"Collision Center","Timezone":"America\/New_York","Type":"AutoBodyShop","Days":[{"Day":"Monday","Hours":[{"From":"7:30","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Tuesday","Hours":[{"From":"7:30","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Wednesday","Hours":[{"From":"7:30","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Thursday","Hours":[{"From":"7:30","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Friday","Hours":[{"From":"7:30","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Saturday","Hours":[{"From":"9:00","To":"12:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Sunday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]}],"Holidays":[{"Day":"4","Month":"Jul","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}],"Name":"4th of July"}],"Vacations":[]},{"Name":"Sales","Timezone":"America\/New_York","Type":"AutoDealer","Days":[{"Day":"Monday","Hours":[{"From":"9:00","To":"7:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Tuesday","Hours":[{"From":"9:00","To":"7:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Wednesday","Hours":[{"From":"9:00","To":"7:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Thursday","Hours":[{"From":"9:00","To":"7:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Friday","Hours":[{"From":"9:00","To":"7:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Saturday","Hours":[{"From":"9:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Sunday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]}],"Holidays":[{"Day":"4","Month":"Jul","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}],"Name":"4th of July"}],"Vacations":[],"Image":""},{"Name":"Service","Timezone":"America\/New_York","Type":"AutoRepair","Days":[{"Day":"Monday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Tuesday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Wednesday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Thursday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Friday","Hours":[{"From":"7:00","To":"6:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Saturday","Hours":[{"From":"8:00","To":"1:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Sunday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]}],"Holidays":[{"Day":"4","Month":"Jul","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}],"Name":"4th of July"}],"Vacations":[],"Image":""},{"Name":"Rental","Timezone":"America\/New_York","Type":"AutoRental","Days":[{"Day":"Monday","Hours":[{"From":"8:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Tuesday","Hours":[{"From":"8:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Wednesday","Hours":[{"From":"8:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Thursday","Hours":[{"From":"8:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Friday","Hours":[{"From":"8:00","To":"5:00","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Saturday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]},{"Day":"Sunday","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}]}],"Holidays":[{"Day":"4","Month":"Jul","Hours":[{"From":"0","To":"0","ToIndication":"PM","FromIndication":"AM"}],"Name":"4th of July"}],"Vacations":[],"Image":""}],"settings":{"dayentryseparator":" ","time_format":"12","warning":"45","warningclosing":"45","removezeroes":true,"includetime":false,"includeday":false,"approximation":true,"loading":"Welcome!","timezone":"America\/New_York"},"i18n":{"days":{"Monday":"Monday","Tuesday":"Tuesday","Wednesday":"Wednesday","Thursday":"Thursday","Frid
9050ay":"Friday","Saturday":"Saturday","Sunday":"Sunday"},"days_short":{"Monday":"Mon","Tuesday":"Tue","Wednesday":"Wed","Thursday":"Thu","Friday":"Fri","Saturday":"Sat","Sunday":"Sun"},"months":{"January":"January","February":"February","March":"March","April":"April","May":"May","June":"June","July":"July","August":"August","September":"September","October":"October","November":"November","December":"December"},"months_short":{"Jan":"Jan","Feb":"Feb","Mar":"Mar","Apr":"Apr","May":"May","Jun":"Jun","Jul":"Jul","Aug":"Aug","Sep":"Sept","Oct":"Oct","Nov":"Nov","Dec":"Dec"},"day":"day","days_text":"days","hour":"hour","hours":"hours","minute":"minute","minutes":"minutes","closed":"Closed"}}; 9051/* ]]> */ 9052</script>
vendor: 1 bytes, line 9052
9052
9053<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/mabel-business-hours-indicator-pro/public/js/public.js?ver=3.3.9' id='mabel-business-hours-indicator-pro-js'></script>
vendor: 1 bytes, line 9053
9053
9054<script type='text/javascript' id='dds-scripts-js-extra'> 9055/* <![CDATA[ */ 9056var get_dds_data = {"ajax_url":"https:\/\/www.hubertvestertoyota.com\/wp\/wp-admin\/admin-ajax.php"}; 9057/* ]]> */ 9058</script>
vendor: 1 bytes, line 9058
9058
9059<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/themes/dv-framework/shortcodes/dropdown-search/dropdown-search.js?ver=1.620.828' id='dds-scripts-js'></script>
vendor: 1 bytes, line 9059
9059
9060<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/themes/dv-framework/shortcodes/searchbox/searchbox.js?ver=1.533.837' id='dv-searchbox-scripts-js'></script>
vendor: 1 bytes, line 9060
9060
9061<script type='text/javascript' id='platform-shadow-js-after'> 9062(function () { 9063 function hydrate() { 9064 // Only act on hosts we mark, and only when the shadow root isn't already present. 9065 var hosts = document.querySelectorAll('.platform-linked-content[data-platform-shadow="1"]'); 9066 for (var i = 0; i < hosts.length; i++) { 9067 var host = hosts[i]; 9068 if (host.shadowRoot || !host.attachShadow) continue; 9069 9070 var t = host.querySelector('template[shadowrootmode]'); 9071 if (!t) continue; 9072 9073 var mode = t.getAttribute('shadowrootmode') || 'open'; 9074 var root = host.attachShadow({ mode: mode }); 9075 9076 root.appendChild(t.content.cloneNode(true)); 9077 t.remove(); 9078 } 9079 } 9080 9081 if (document.readyState === 'loading') { 9082 document.addEventListener('DOMContentLoaded', hydrate); 9083 } else { 9084 hydrate(); 9085 } 9086})(); 9087</script>
vendor: 1 bytes, line 9087
9087
9088<script type='text/javascript' id='da-merge-tags-js-extra'> 9089/* <![CDATA[ */ 9090var daMergeTags = {"timezone":"America\/New_York"}; 9091/* ]]> */ 9092</script>
vendor: 1 bytes, line 9092
9092
9093<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/themes/dv-framework/components/Utils/merge-tags.min.js?ver=1.784.48' id='da-merge-tags-js'></script>
vendor: 1 bytes, line 9093
9093
9094<script type='text/javascript' id='get_srp_form-js-extra'> 9095/* <![CDATA[ */ 9096var get_srp_form = {"ajax_url":"https:\/\/www.hubertvestertoyota.com\/wp\/wp-admin\/admin-ajax.php"}; 9097/* ]]> */ 9098</script>
vendor: 1 bytes, line 9098
9098
9099<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/srp-ajax.js?ver=1.776.838' id='get_srp_form-js'></script>
vendor: 1 bytes, line 9099
9099
9100<script type='text/javascript' id='script-ga4-js-extra'> 9101/* <![CDATA[ */ 9102var AGEventManagerOptions = {"debug":"","trackingIDs":["G-32FXJLL18G","G-M3B4B59Q4Z"]}; 9103/* ]]> */ 9104</script>
vendor: 1 bytes, line 9104
9104
9105<script type="module" src="https://www.hubertvestertoyota.com/app/themes/dv-framework/components/EventsManager/public/latest.js?ver=1790226195"></script>
9105<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/gravityforms/js/jquery.maskedinput.min.js?ver=2.4.6' id='gform_masked_input-js'></script>
vendor: 1 bytes, line 9105
9105
9106<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/gravityforms/js/placeholders.jquery.min.js?ver=2.4.6' id='gform_placeholder-js'></script>
9106 9107 <div class="ag-kia-window-sticker-modal" data-kia-window-sticker-modal aria-hidden="true"> 9108 <div class="ag-kia-window-sticker-modal__backdrop" data-kia-window-sticker-close></div> 9109 <div class="ag-kia-window-sticker-modal__dialog" role="dialog" aria-modal="true" aria-label="Factory Window Sticker"> 9110 <button class="ag-kia-window-sticker-modal__close" type="button" data-kia-window-sticker-close aria-label="Close window sticker">×</button> 9111 <iframe class="ag-kia-window-sticker-modal__iframe" data-kia-window-sticker-frame title="Factory Window Sticker"></iframe> 9112 </div> 9113 </div> 9114 <style> 9115 .ag-kia-window-sticker-modal { 9116 position: fixed; 9117 z-index: 999999; 9118 top: 0; 9119 right: 0; 9120 bottom: 0; 9121 left: 0; 9122 display: none; 9123 } 9124 .ag-kia-window-sticker-modal.is-open { 9125 display: block; 9126 } 9127 .ag-kia-window-sticker-modal__backdrop { 9128 position: absolute; 9129 top: 0; 9130 right: 0; 9131 bottom: 0; 9132 left: 0; 9133 background: rgba(0, 0, 0, 0.72); 9134 } 9135 .ag-kia-window-sticker-modal__dialog { 9136 position: absolute; 9137 top: 50%; 9138 left: 50%; 9139 width: 82vw; 9140 max-width: 1560px; 9141 height: 88vh; 9142 max-height: 980px; 9143 transform: translate(-50%, -50%); 9144 background: #fff; 9145 box-shadow: 0 18px 48px rgba(0, 0, 0, 0.35); 9146 } 9147 .ag-kia-window-sticker-modal__close { 9148 position: absolute; 9149 z-index: 1; 9150 top: 8px; 9151 right: 10px; 9152 width: 34px; 9153 height: 34px; 9154 border: 0; 9155 border-radius: 50%; 9156 background: #222; 9157 color: #fff; 9158 font-size: 26px; 9159 line-height: 30px; 9160 cursor: pointer; 9161 } 9162 .ag-kia-window-sticker-modal__iframe { 9163 width: 100%; 9164 height: 100%; 9165 border: 0; 9166 } 9167 body.ag-kia-window-sticker-modal-open { 9168 overflow: hidden; 9169 } 9170 @media (max-width: 767px) { 9171 .ag-kia-window-sticker-modal__dialog { 9172 width: calc(100vw - 20px); 9173 height: calc(100vh - 20px); 9174 max-height: none; 9175 } 9176 } 9177 </style> 9178
9178<script> 9179 (function () { 9180 var modal = document.querySelector('[data-kia-window-sticker-modal]'); 9181 var frame = document.querySelector('[data-kia-window-sticker-frame]'); 9182 var activeTrigger = null; 9183 9184 if (!modal || !frame) { 9185 return; 9186 } 9187 9188 function open(url, trigger) { 9189 activeTrigger = trigger || null; 9190 frame.setAttribute('src', url); 9191 modal.classList.add('is-open'); 9192 modal.setAttribute('aria-hidden', 'false'); 9193 document.body.classList.add('ag-kia-window-sticker-modal-open'); 9194 } 9195 9196 function close() { 9197 modal.classList.remove('is-open'); 9198 modal.setAttribute('aria-hidden', 'true'); 9199 frame.removeAttribute('src'); 9200 document.body.classList.remove('ag-kia-window-sticker-modal-open'); 9201 9202 if (activeTrigger && typeof activeTrigger.focus === 'function') { 9203 activeTrigger.focus(); 9204 } 9205 } 9206 9207 function closest(element, selector) { 9208 while (element && element !== document) { 9209 if (element.matches && element.matches(selector)) { 9210 return element; 9211 } 9212 9213 element = element.parentNode; 9214 } 9215 9216 return null; 9217 } 9218 9219 window.AutoGoKiaWindowSticker = { 9220 open: open, 9221 close: close 9222 }; 9223 9224 document.addEventListener('click', function (event) { 9225 var link = closest(event.target, '[data-kia-window-sticker-link]'); 9226 9227 if (!link) { 9228 link = closest(event.target, 'a[href*="/kia-window-sticker/"]'); 9229 } 9230 9231 if (link) { 9232 event.preventDefault(); 9233 event.stopImmediatePropagation(); 9234 open(link.href, link); 9235 } 9236 }, true); 9237 9238 document.addEventListener('click', function (event) { 9239 if (!closest(event.target, '[data-kia-window-sticker-close]')) { 9240 return; 9241 } 9242 9243 event.preventDefault(); 9244 close(); 9245 }); 9246 9247 document.addEventListener('keyup', function (event) { 9248 if ((event.key === 'Escape' || event.keyCode === 27) && modal.classList.contains('is-open')) { 9249 close(); 9250 } 9251 }); 9252 })(); 9253 </script>
9253 9254 <!-- HFCM by 99 Robots - Snippet # 6: Drive Centric Chat -->
9255<script> 9256window.ignitifySettings = { ignitifyId: "eecfe771-1e25-4a66-98d8-3b29fb7d8693" }; 9257</script>
9257 9258
9259<script> 9260(function () { var w = window; var ic = w.Ignitify; if (typeof ic === 'function') { ic('reattach_activator'); ic('update', w.ignitifySettings); } else { var d = document; var i = function () { i.c(arguments); }; i.q = []; i.c = function (args) { i.q.push(args); }; w.Ignitify = i; var l = function () { var s = d.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'https://ignitify-tagmanager-scripts.drivecentric.io/prod/ignitify-tagmanager.js'; var x = d.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); }; if (document.readyState === 'complete') { l(); } else if (w.attachEvent) { w.attachEvent('onload', l); } else { w.addEventListener('load', l, false); } } })(); 9261</script>
9261 9262<!-- /end HFCM by 99 Robots --> 9263<!-- HFCM by 99 Robots - Snippet # 4: ComplyAuto Body Script -->
9264<script src="https://cdn.complyauto.com/cookiebanner/banner.js" data-cacookieconsent-id="43a2cf52-cba9-449b-b369-96150e045d6a"></script>
9264 9265<!-- /end HFCM by 99 Robots --> 9266<!-- HFCM by 99 Robots - Snippet # 2: USERway -->
9267<script src="https://cdn.userway.org/widget.js" data-account="SNSTzAU4BD"></script>
9267 9268<!-- /end HFCM by 99 Robots --> 9269 <!-- AutoGO -->
9270<script type="text/javascript"> 9271 var _paq = window._paq || []; 9272 /* tracker methods like "setCustomDimension" should be called before "trackPageView" */ 9273 _paq.push(['trackPageView']); 9274 _paq.push(['enableLinkTracking']); 9275 (function() { 9276 var u="https://analytics.autogo.ai/"; 9277 _paq.push(['setTrackerUrl', u+'js/tracker.php']); 9278 _paq.push(['setSiteId', '352']); 9279 var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; 9280 g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'js/tracker.php'; s.parentNode.insertBefore(g,s); 9281 })(); 9282</script>
9282 9283<!-- End AutoGO Code --> 9284
9285<script type="application/ld+json" data-type="generalSchema"> 9286{ 9287 "@context": "https://www.schema.org", 9288 "@type": "AutoDealer", 9289 "@id": "https://www.hubertvestertoyota.com/#hubertvestertoyota", 9290 "priceRange": "$-$$$", 9291 "name": "Hubert Vester Toyota", 9292 "url": "https://www.hubertvestertoyota.com", 9293 "telephone": "252.293.6513", 9294 "image": "https://bucket.dealeralchemist.com/hubert-vester-toyota/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200", 9295 "logo": "https://bucket.dealeralchemist.com/hubert-vester-toyota/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200", 9296 "address": { 9297 "@type": "PostalAddress", 9298 "streetAddress": "3712 Raleigh Rd Pkwy W", 9299 "addressLocality": "Wilson", 9300 "addressRegion": "NC", 9301 "postalCode": "27896", 9302 "addressCountry": "US" 9303}, 9304 "openingHoursSpecification": [ 9305 { 9306 "@type": "OpeningHoursSpecification", 9307 "dayOfWeek": [ 9308 "Monday", 9309 "Tuesday", 9310 "Wednesday", 9311 "Thursday", 9312 "Friday" 9313 ], 9314 "opens": "07:00", 9315 "closes": "18:00" 9316 }, 9317 { 9318 "@type": "OpeningHoursSpecification", 9319 "dayOfWeek": [ 9320 "Saturday" 9321 ], 9322 "opens": "08:00", 9323 "closes": "13:00" 9324 }, 9325 { 9326 "@type": "OpeningHoursSpecification", 9327 "dayOfWeek": [ 9328 "Sunday" 9329 ], 9330 "opens": "00:00", 9331 "closes": "12:00" 9332 }, 9333 { 9334 "@type": "OpeningHoursSpecification", 9335 "dayOfWeek": [ 9336 "Monday", 9337 "Tuesday", 9338 "Wednesday", 9339 "Thursday", 9340 "Friday" 9341 ], 9342 "opens": "07:30", 9343 "closes": "17:00" 9344 }, 9345 { 9346 "@type": "OpeningHoursSpecification", 9347 "dayOfWeek": [ 9348 "Saturday" 9349 ], 9350 "opens": "09:00", 9351 "closes": "12:00" 9352 }, 9353 { 9354 "@type": "OpeningHoursSpecification", 9355 "dayOfWeek": [ 9356 "Sunday" 9357 ], 9358 "opens": "00:00", 9359 "closes": "12:00" 9360 }, 9361 { 9362 "@type": "OpeningHoursSpecification", 9363 "dayOfWeek": [ 9364 "Monday", 9365 "Tuesday", 9366 "Wednesday", 9367 "Thursday", 9368 "Friday" 9369 ], 9370 "opens": "09:00", 9371 "closes": "19:00" 9372 }, 9373 { 9374 "@type": "OpeningHoursSpecification", 9375 "dayOfWeek": [ 9376 "Saturday" 9377 ], 9378 "opens": "09:00", 9379 "closes": "17:00" 9380 }, 9381 { 9382 "@type": "OpeningHoursSpecification", 9383 "dayOfWeek": [ 9384 "Sunday" 9385 ], 9386 "opens": "00:00", 9387 "closes": "12:00" 9388 }, 9389 { 9390 "@type": "OpeningHoursSpecification", 9391 "dayOfWeek": [ 9392 "Monday", 9393 "Tuesday", 9394 "Wednesday", 9395 "Thursday", 9396 "Friday" 9397 ], 9398 "opens": "07:00", 9399 "closes": "18:00" 9400 }, 9401 { 9402 "@type": "OpeningHoursSpecification", 9403 "dayOfWeek": [ 9404 "Saturday" 9405 ], 9406 "opens": "08:00", 9407 "closes": "13:00" 9408 }, 9409 { 9410 "@type": "OpeningHoursSpecification", 9411 "dayOfWeek": [ 9412 "Sunday" 9413 ], 9414 "opens": "00:00", 9415 "closes": "12:00" 9416 }, 9417 { 9418 "@type": "OpeningHoursSpecification", 9419 "dayOfWeek": [ 9420 "Monday", 9421 "Tuesday", 9422 "Wednesday", 9423 "Thursday", 9424 "Friday" 9425 ], 9426 "opens": "08:00", 9427 "closes": "17:00" 9428 }, 9429 { 9430 "@type": "OpeningHoursSpecification", 9431 "dayOfWeek": [ 9432 "Saturday", 9433 "Sunday" 9434 ], 9435 "opens": "00:00", 9436 "closes": "12:00" 9437 } 9438], 9439 "department": [ 9440 { 9441 "@type": "AutoPartsStore", 9442 "priceRange": "$-$$$", 9443 "name": "Parts", 9444 "address": { 9445 "@type": "PostalAddress", 9446 "streetAddress": "3712 Raleigh Rd Pkwy W", 9447 "addressLocality": "Wilson", 9448 "addressRegion": "NC", 9449 "postalCode": "27896", 9450 "addressCountry": "US" 9451 }, 9452 "telephone": "252.293.6513", 9453 "openingHoursSpecification": [ 9454 { 9455 "@type": "OpeningHoursSpecification", 9456 "dayOfWeek": [ 9457 "Monday", 9458 "Tuesday", 9459 "Wednesday", 9460 "Thursday", 9461 "Friday" 9462 ], 9463 "opens": "07:00", 9464 "closes": "18:00" 9465 }, 9466 { 9467 "@type": "OpeningHoursSpecification", 9468 "dayOfWeek": [ 9469 "Saturday" 9470 ], 9471 "opens": "08:00", 9472 "closes": "13:00" 9473 }, 9474 { 9475 "@type": "OpeningHoursSpecification", 9476 "dayOfWeek": [ 9477 "Sunday" 9478 ], 9479 "opens": "00:00", 9480 "closes": "12:00" 9481 } 9482 ], 9483 "image": "https:\/\/bucket.dealeralchemist.com\/hubert-vester-toyota\/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200" 9484 }, 9485 { 9486 "@type": "AutoBodyShop", 9487 "priceRange": "$-$$$", 9488 "name": "Collision Center", 9489 "address": { 9490 "@type": "PostalAddress", 9491 "streetAddress": "3712 Raleigh Rd Pkwy W", 9492 "addressLocality": "Wilson", 9493 "addressRegion": "NC", 9494 "postalCode": "27896", 9495 "addressCountry": "US" 9496 }, 9497 "telephone": "252.293.6513", 9498 "openingHoursSpecification": [ 9499 { 9500 "@type": "OpeningHoursSpecification", 9501 "dayOfWeek": [ 9502 "Monday", 9503 "Tuesday", 9504 "Wednesday", 9505 "Thursday", 9506 "Friday" 9507 ], 9508 "opens": "07:30", 9509 "closes": "17:00" 9510 }, 9511 { 9512 "@type": "OpeningHoursSpecification", 9513 "dayOfWeek": [ 9514 "Saturday" 9515 ], 9516 "opens": "09:00", 9517 "closes": "12:00" 9518 }, 9519 { 9520 "@type": "OpeningHoursSpecification", 9521 "dayOfWeek": [ 9522 "Sunday" 9523 ], 9524 "opens": "00:00", 9525 "closes": "12:00" 9526 } 9527 ], 9528 "image": "https:\/\/bucket.dealeralchemist.com\/hubert-vester-toyota\/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200" 9529 }, 9530 { 9531 "@type": "AutoDealer", 9532 "priceRange": "$-$$$", 9533 "name": "Sales", 9534 "address": { 9535 "@type": "PostalAddress", 9536 "streetAddress": "3712 Raleigh Rd Pkwy W", 9537 "addressLocality": "Wilson", 9538 "addressRegion": "NC", 9539 "postalCode": "27896", 9540 "addressCountry": "US" 9541 }, 9542 "telephone": "252.293.6513", 9543 "openingHoursSpecification": [ 9544 { 9545 "@type": "OpeningHoursSpecification", 9546 "dayOfWeek": [ 9547 "Monday", 9548 "Tuesday", 9549 "Wednesday", 9550 "Thursday", 9551 "Friday" 9552 ], 9553 "opens": "09:00", 9554 "closes": "19:00" 9555 }, 9556 { 9557 "@type": "OpeningHoursSpecification", 9558 "dayOfWeek": [ 9559 "Saturday" 9560 ], 9561 "opens": "09:00", 9562 "closes": "17:00" 9563 }, 9564 { 9565 "@type": "OpeningHoursSpecification", 9566 "dayOfWeek": [ 9567 "Sunday" 9568 ], 9569 "opens": "00:00", 9570 "closes": "12:00" 9571 } 9572 ], 9573 "image": "https:\/\/bucket.dealeralchemist.com\/hubert-vester-toyota\/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200" 9574 }, 9575 { 9576 "@type": "AutoRepair", 9577 "priceRange": "$-$$$", 9578 "name": "Service", 9579 "address": { 9580 "@type": "PostalAddress", 9581 "streetAddress": "3712 Raleigh Rd Pkwy W", 9582 "addressLocality": "Wilson", 9583 "addressRegion": "NC", 9584 "postalCode": "27896", 9585 "addressCountry": "US" 9586 }, 9587 "telephone": "252.293.6513", 9588 "openingHoursSpecification": [ 9589 { 9590 "@type": "OpeningHoursSpecification", 9591 "dayOfWeek": [ 9592 "Monday", 9593 "Tuesday", 9594 "Wednesday", 9595 "Thursday", 9596 "Friday" 9597 ], 9598 "opens": "07:00", 9599 "closes": "18:00" 9600 }, 9601 { 9602 "@type": "OpeningHoursSpecification", 9603 "dayOfWeek": [ 9604 "Saturday" 9605 ], 9606 "opens": "08:00", 9607 "closes": "13:00" 9608 }, 9609 { 9610 "@type": "OpeningHoursSpecification", 9611 "dayOfWeek": [ 9612 "Sunday" 9613 ], 9614 "opens": "00:00", 9615 "closes": "12:00" 9616 } 9617 ], 9618 "image": "https:\/\/bucket.dealeralchemist.com\/hubert-vester-toyota\/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200" 9619 }, 9620 { 9621 "@type": "AutoRental", 9622 "priceRange": "$-$$$", 9623 "name": "Rental", 9624 "address": { 9625 "@type": "PostalAddress", 9626 "streetAddress": "3712 Raleigh Rd Pkwy W", 9627 "addressLocality": "Wilson", 9628 "addressRegion": "NC", 9629 "postalCode": "27896", 9630 "addressCountry": "US" 9631 }, 9632 "telephone": "252.293.6513", 9633 "openingHoursSpecification": [ 9634 { 9635 "@type": "OpeningHoursSpecification", 9636 "dayOfWeek": [ 9637 "Monday", 9638 "Tuesday", 9639 "Wednesday", 9640 "Thursday", 9641 "Friday" 9642 ], 9643 "opens": "08:00", 9644 "closes": "17:00" 9645 }, 9646 { 9647 "@type": "OpeningHoursSpecification", 9648 "dayOfWeek": [ 9649 "Saturday", 9650 "Sunday" 9651 ], 9652 "opens": "00:00", 9653 "closes": "12:00" 9654 } 9655 ], 9656 "image": "https:\/\/bucket.dealeralchemist.com\/hubert-vester-toyota\/HV-Toyota-Black.png?auto=compress%2Cformat&ixlib=php-3.3.1&w=200" 9657 } 9658]} 9659</script>
9659 9660<link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='dv-dealer-reviews-badge-css' href='https://www.hubertvestertoyota.com/app/themes/dv-framework/media/css/dv-reviews/badge/dv-reviews-badge.css?ver=1.771.862' type='text/css' media='all' /><link rel='preload' as='style' onload="this.onload=null;this.rel='stylesheet'" id='itsg_progresszero_css' href='https://www.hubertvestertoyota.com/app/plugins/gravity-forms-start-progress-bar-at-zero-percent/css/itsg_progresszero_css.min.css?ver=1.2.0' type='text/css' media='all' />
9660<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/gravityforms/js/jquery.json.min.js?ver=2.4.6' id='gform_json-js'></script>
vendor: 1 bytes, line 9660
9660
9661<script type='text/javascript' id='gform_gravityforms-js-extra'> 9662/* <![CDATA[ */ 9663var gform_gravityforms = {"strings":{"invalid_file_extension":"This type of file is not allowed. Must be one of the following: ","delete_file":"Delete this file","in_progress":"in progress","file_exceeds_limit":"File exceeds size limit","illegal_extension":"This type of file is not allowed.","max_reached":"Maximum number of files reached","unknown_error":"There was a problem while saving the file on the server","currently_uploading":"Please wait for the uploading to complete","cancel":"Cancel","cancel_upload":"Cancel this upload","cancelled":"Cancelled"},"vars":{"images_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images"}}; 9664var gform_gravityforms = {"strings":{"invalid_file_extension":"This type of file is not allowed. Must be one of the following: ","delete_file":"Delete this file","in_progress":"in progress","file_exceeds_limit":"File exceeds size limit","illegal_extension":"This type of file is not allowed.","max_reached":"Maximum number of files reached","unknown_error":"There was a problem while saving the file on the server","currently_uploading":"Please wait for the uploading to complete","cancel":"Cancel","cancel_upload":"Cancel this upload","cancelled":"Cancelled"},"vars":{"images_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images"}}; 9665var gform_gravityforms = {"strings":{"invalid_file_extension":"This type of file is not allowed. Must be one of the following: ","delete_file":"Delete this file","in_progress":"in progress","file_exceeds_limit":"File exceeds size limit","illegal_extension":"This type of file is not allowed.","max_reached":"Maximum number of files reached","unknown_error":"There was a problem while saving the file on the server","currently_uploading":"Please wait for the uploading to complete","cancel":"Cancel","cancel_upload":"Cancel this upload","cancelled":"Cancelled"},"vars":{"images_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images"}}; 9666var gform_gravityforms = {"strings":{"invalid_file_extension":"This type of file is not allowed. Must be one of the following: ","delete_file":"Delete this file","in_progress":"in progress","file_exceeds_limit":"File exceeds size limit","illegal_extension":"This type of file is not allowed.","max_reached":"Maximum number of files reached","unknown_error":"There was a problem while saving the file on the server","currently_uploading":"Please wait for the uploading to complete","cancel":"Cancel","cancel_upload":"Cancel this upload","cancelled":"Cancelled"},"vars":{"images_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images"}}; 9667var gform_gravityforms = {"strings":{"invalid_file_extension":"This type of file is not allowed. Must be one of the following: ","delete_file":"Delete this file","in_progress":"in progress","file_exceeds_limit":"File exceeds size limit","illegal_extension":"This type of file is not allowed.","max_reached":"Maximum number of files reached","unknown_error":"There was a problem while saving the file on the server","currently_uploading":"Please wait for the uploading to complete","cancel":"Cancel","cancel_upload":"Cancel this upload","cancelled":"Cancelled"},"vars":{"images_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images"}}; 9668/* ]]> */ 9669</script>
vendor: 1 bytes, line 9669
9669
9670<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/gravityforms/js/gravityforms.min.js?ver=2.4.6' id='gform_gravityforms-js'></script>
vendor: 1 bytes, line 9670
9670
9671<script type='text/javascript' src='https://www.hubertvestertoyota.com/app/plugins/gravityforms/js/conditional_logic.min.js?ver=2.4.6' id='gform_conditional_logic-js'></script>
vendor: 1 bytes, line 9671
9671
9672<script type='text/javascript'> if(typeof gf_global == 'undefined') var gf_global = {"gf_currency_config":{"name":"U.S. Dollar","symbol_left":"$","symbol_right":"","symbol_padding":"","thousand_separator":",","decimal_separator":".","decimals":2},"base_url":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms","number_formats":[],"spinnerUrl":"https:\/\/www.hubertvestertoyota.com\/app\/plugins\/gravityforms\/images\/spinner.gif"};jQuery(document).bind('gform_post_render', function(event, formId, currentPage){if(formId == 7) {if(typeof Placeholders != 'undefined'){ 9673 Placeholders.enable(); 9674 }jQuery('#input_7_3').mask('(999) 999-9999').bind('keypress', function(e){if(e.which == 13){jQuery(this).blur();} } );} } );jQuery(document).bind('gform_post_conditional_logic', function(event, formId, fields, isInit){} );</script>
9674<script type='text/javascript'> jQuery(document).ready(function(){jQuery(document).trigger('gform_post_render', [7, 1]) } ); </script>
9674<style> 9675 #browser-warning { 9676 position: fixed; 9677 top: -160px; 9678 left: 0; 9679 right: 0; 9680 background-color: #ff9800; 9681 color: white; 9682 text-align: center; 9683 padding: 15px; 9684 font-size: 16px; 9685 z-index: 1000; 9686 box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); 9687 transition: top 0.5s ease-in-out; 9688 } 9689 #browser-warning a { 9690 color: #fff; 9691 text-decoration: underline; 9692 font-weight: bold; 9693 } 9694 #browser-warning .dismiss-button { 9695 background: white; 9696 padding: 5px 10px; 9697 border-radius: 2px; 9698 border: none; 9699 color: #ff9800; 9700 font-size: 16px; 9701 cursor: pointer; 9702 margin-top: 8px; 9703 } 9704 </style> 9705 9706 9707<div id="browser-warning"> 9708 Your browser is out of date. Please <a href="https://browsehappy.com/" target="_blank">update your browser</a> for 9709 the best experience. 9710</div> 9711 9712
9712<script> 9713 const OUTDATED_IOS_VERSION = 17; // iOS version considered outdated 9714 9715 function isBrowserOutdated() { 9716 const ua = navigator.userAgent; 9717 const isOldBrowser = !( 9718 'fetch' in window && 9719 'Promise' in window && 9720 'assign' in Object 9721 ); // Simple feature detection for modern JS APIs 9722 const isOldIE = /MSIE|Trident/.test(ua); // Detect old IE versions 9723 return isOldBrowser || isOldIE; 9724 } 9725 9726 function isIOSOutdated() { 9727 const ua = navigator.userAgent; 9728 const isIOS = /iPad|iPhone|iPod/.test(ua) && !window.MSStream; 9729 if (isIOS) { 9730 const iosVersion = ua.match(/OS (\d+)_/); 9731 if (iosVersion && iosVersion[1]) { 9732 return parseInt(iosVersion[1], 10) < OUTDATED_IOS_VERSION; // Assume iOS < OUTDATED_IOS_VERSION is outdated 9733 } 9734 } 9735 return false; 9736 } 9737 9738 function isAndroidOutdated() { 9739 const ua = navigator.userAgent.toLowerCase(); 9740 const isAndroid = ua.includes("android"); 9741 if (isAndroid) { 9742 const isOldBrowser = !('fetch' in window && 'Promise' in window && 'assign' in Object); 9743 return isOldBrowser; 9744 } 9745 return false; 9746 } 9747 9748 function showBrowserWarning(message) { 9749 const dismissButton = document.createElement('button');
9750 dismissButton.classList = 'dismiss-button'; 9751 dismissButton.innerText = 'Dismiss'; 9752 dismissButton.style.marginLeft = '15px'; 9753 dismissButton.onclick = function() { 9754 const warning = document.getElementById('browser-warning'); 9755 warning.style.top = '-160px'; // Slide up 9756 localStorage.setItem('ag-browser-warning-dismissed', 'true'); 9757 }; 9758 const warning = document.getElementById('browser-warning'); 9759 warning.innerHTML = message; 9760 warning.appendChild(document.createElement('br')); 9761 warning.appendChild(dismissButton); 9762 warning.style.top = '0'; // Slide down 9763 } 9764 9765 function checkBrowser() { 9766 if (localStorage.getItem('ag-browser-warning-dismissed') === 'true') { 9767 return; 9768 } 9769 if (isBrowserOutdated()) { 9770 showBrowserWarning( 9771 'Your browser is out of date.<br/>Please <a href="https://browsehappy.com/" target="_blank">update your browser</a> for the best experience.' 9772 ); 9773 } else if (isIOSOutdated()) { 9774 showBrowserWarning( 9775 'Your iOS version is outdated.<br/>Please update your iOS version to get the latest browser updates.' 9776 ); 9777 } else if (isAndroidOutdated()) { 9778 showBrowserWarning( 9779 'Your Android browser is outdated.<br/>Please update your browser from the <a href="https://play.google.com/store/apps/details?id=com.android.chrome" target="_blank">Google Play Store</a>.' 9780 ); 9781 } 9782 } 9783 9784 window.onload = checkBrowser; 9785 </script>
9785 9786 9787<!-- <style> 9788body .buorg { 9789 border-color: #646464; 9790 color: #fff; 9791 background-color: #141518; 9792} 9793</style> 9794
9795<script> 9796var $buoop = {required:{e:-4,f:-4,o:-4,s:-2,c:-4},insecure:true,api:2021.10 }; 9797function $buo_f(){ 9798 var e = document.createElement("script"); 9799 e.src = "//browser-update.org/update.min.js"; 9800 document.body.appendChild(e); 9801}; 9802try {document.addEventListener("DOMContentLoaded", $buo_f,false)} 9803catch(e){window.attachEvent("onload", $buo_f)} 9804</script>
9804 --> 9805</script>
vendor: 1 bytes, line 9805
9805
9806<script type="text/javascript"> 9807// Toggle nav-below hamburger icon 9808jQuery(document).ready(function() { 9809 jQuery('.roll-out-btn').click(function() { 9810 jQuery('.roll-out-btn').toggleClass('roll-out-btn-open'); 9811 jQuery('.roll-out-menu').toggleClass('roll-out-open'); 9812 jQuery('.rollout-frame').toggleClass('rollout-frame-open'); 9813 jQuery('.save-btn').toggleClass('save-btn-saved'); 9814 9815 }); 9816 9817 // Toggle Side Menu 9818 $('#nav-icon3').click(function() { 9819 $("body").toggleClass('menu-open'); 9820 $("#dv-sidenav").toggleClass("dv-sidenav-open"); 9821 }); 9822 9823 }); 9824 9825 9826 9827/* DV-41585: swap header Google reviews badge for the smaller review pill (same markup the theme uses on its pill header sites) */ 9828(function(){ 9829 function swap(){ 9830 var wrap=document.querySelector('.ag-dealer-reviews'); 9831 if(!wrap||wrap.querySelector('.dv-mini-badge')) return; 9832 var badge=wrap.querySelector('.dv-reviews-badge'); 9833 if(!badge) return; 9834 var score=(badge.querySelector('.dv-reviews-badge-score')||{}).textContent||''; 9835 score=(score||'').trim(); 9836 if(!score) return; 9837 var inverse=badge.classList.contains('dv-reviews-inverse'); 9838 var pill=document.createElement('div'); 9839 pill.className='dv-mini-badge-container'; 9840 pill.innerHTML='<div class="dv-mini-badge'+(inverse?' dv-reviews-inverse':'')+'"><img src="https://bucket.dealeralchemist.com/assets/reviews/google_small_icon.png?auto=compress%2Cformat&ixlib=php-1.2.1&h=16" alt="Google Logo"> <span>'+score+'</span> <i class="fas fa-star"></i></div>'; 9841 badge.parentNode.replaceChild(pill,badge); 9842 } 9843 if(document.readyState==='loading') document.addEventListener('DOMContentLoaded',swap); else swap();
9844 var tries=0; var t=setInterval(function(){ swap(); if(document.querySelector('.dv-mini-badge')||++tries>20) clearInterval(t); },500); 9845})(); 9846</script>
9846 9847
9848<script> 9849/** 9850 * Removing SDA events on all anchors 9851 * Due to an issue with android issue 9852 */ 9853var removeSDCTAEvent = function(){ 9854 var el = document.querySelectorAll('a'); 9855 for (i = 0; i < el.length; ++i) { 9856 if(el[i].hasAttribute("data-sda-event")) { 9857 if(el[i].getAttribute("data-sda-event") == 'clickToCall'){ 9858 var propVal = ''; 9859 if(el[i].getAttribute("data-sda-event-set-prop")){ 9860 propVal = el[i].getAttribute("data-sda-event-set-prop"); 9861 propVal = propVal.split("|"); 9862 propVal = propVal[1]; 9863 } 9864 el[i].removeAttribute("data-sda-event"); 9865 el[i].removeAttribute("data-sda-event-set-prop"); 9866 el[i].setAttribute("data-ag-event", 'clickToCall|'+propVal) 9867 } 9868 if(el[i].getAttribute("data-sda-event") == 'getDirections'){ 9869 el[i].removeAttribute("data-sda-event"); 9870 el[i].setAttribute("data-ag-event", 'getDirections'); 9871 } 9872 } 9873 } 9874}; 9875 9876// removeSDCTAEvent(); 9877//setInterval(removeSDCTAEvent, 10000); 9878</script>
9878 9879 9880 9881 9882
9882<script>/*Copyright 2011-2015 iPerceptions, Inc. All rights reserved. Do not distribute.iPerceptions provides this code 'as is' without warranty of any kind, either express or implied. */ window.iperceptionskey = '6d1fdf1a-2979-42c3-82c9-6ae3384d9f05';(function () { var a = document.createElement('script'),b = document.getElementsByTagName('body')[0]; a.type = 'text/javascript'; a.async = true;a.src = '//universal.iperceptions.com/wrapper.js';b.appendChild(a);})();</script>
9882 9883 9884
9884<script> 9885 var scheduleServiceIframeURL = "https://consumer.xtime.com/scheduling/?webKey=HUBERTVESTERTOYO&skipRedirect=true&WMODE=true"; 9886 </script>
9886 9887
9887<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/catch-schedule-service-btn.js"></script>
9887 9888 9889 9890 9891 9892
9892<script> 9893 var customModalsLinks = [{"trigger_slug":"schedule","target_url":"https:\/\/consumer.xtime.com\/scheduling\/?webKey=HUBERTVESTERTOYO&skipRedirect=true&WMODE=true"}]; 9894 </script>
9894 9895 9896
9896<script src="https://www.hubertvestertoyota.com/app/themes/dv-framework/media/js/auto-modal.js" defer></script>
9896 9897 </footer> 9898 </body> 9899 9900</html>
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.