1function openMenu(){ 2 this.classList.toggle('open'); 3 if(this.classList.contains('open')){ 4 document.querySelector('body').style.overflow = 'hidden'; 5 }else{ 6 document.querySelector('body').style.overflow = 'visible'; 7 } 8} 9 10 11function collapseLink(){ 12 this.classList.toggle('on'); 13} 14 15function setOptSlider(args) { 16 var spaceBetween; 17 let autoplay = args['autoplay'] !== undefined ? args['autoplay'] : false; 18 let autoplay_mob = args['autoplay_mob'] !== undefined ? args['autoplay_mob'] : false; 19 let mobile_step = parseInt(customVar.swiper_mobile_step); 20 let wrapperName = args['wrapperName']; 21 let slidername = args['slidername']; 22 let items = args['items']; 23 let nav = args['nav']; 24 let dots = args['dots']; 25 let classNav = args['classNav']; 26 let classDots = args['classDots']; 27 let loop = args['loop']; 28 let items_mob = args['items_mob']; 29 let nav_mob = args['nav_mob']; 30 let dots_mob = args['dots_mob']; 31 let loop_mob = args['loop_mob']; 32 let row_mob = args['row_mob']; 33 let showItemsTablet = ('items_to_show_tablet' in args) && args['items_to_show_tablet'] ? args['items_to_show_tablet'] : items; 34 let incNav_DotInCont = args['include_nav_dots_in_container']; 35 let autoplayConfig = false 36 if (slidername.includes('swiper-hero')) { 37 spaceBetween = 4; 38 }else{ 39 spaceBetween = 20; 40 } 41 42 43 if(window.innerWidth >= 992) { 44 autoplayConfig = autoplay ? { delay: 7000, disableOnInteraction: false } : false; 45 } else if(window.innerWidth < 768) { 46 autoplayConfig = autoplay_mob ? { delay: 7000, disableOnInteraction: false } : false; 47 } 48 // SwiperConfig 49 const swiperConfig = { 50 direction: 'horizontal', 51 spaceBetween: spaceBetween, 52 scrollbar: { 53 el: '.swiper-pagination', 54 clickable: true 55 }, 56 breakpoints: { 57 0: { 58 slidesPerView: items_mob, 59 loop: loop_mob, 60 grid: { 61 rows: row_mob 62 }, 63 }, 64 768 : { 65 slidesPerView: showItemsTablet, 66 loop: false, 67 grid: { 68 rows: 1 69 } 70 }, 71 992 : { 72 slidesPerView: items, 73 loop: loop, 74 grid: { 75 rows: 1 76 } 77 }, 78 }, 79 // For accessibility 80 a11y: { 81 enabled: true, 82 prevSlideMessage: 'Go to previous slide', 83 nextSlideMessage: 'Go to next slide', 84 paginationBulletMessage: 'Go to slide {{index}}', 85 }, 86 keyboard: { 87 enabled: true, // Abilita la navigazione da tastiera 88 onlyInViewport: true, // Funziona solo quando lo slider è visibile 89 }, 90 autoplay: autoplayConfig, 91 }; 92 93 if(autoplayConfig){ 94 swiperConfig.speed = 800; 95 swiperConfig.effect = 'fade'; 96 swiperConfig.fadeEffect = { 97 crossFade: true 98 } 99 } 100 101 // Add dots if enabled 102 if (dots) { 103 swiperConfig.pagination = { 104 el: '.swiper-pagination', 105 clickable: true 106 }; 107 } 108 109 // Add dots for mobile if enabled 110 if (!dots_mob && window.innerWidth <= 768) { 111 delete swiperConfig.pagination; 112 }else if(dots_mob && window.innerWidth <= 768){ 113 swiperConfig.pagination = { 114 el: '.swiper-pagination', 115 clickable: true 116 }; 117 } 118 119 // Add navigation if enabled 120 if (nav) { 121 swiperConfig.navigation = { 122 nextEl: '.swiper-button-next', 123 prevEl: '.swiper-button-prev' 124 }; 125 } 126 127 // Remove navigation in mobile if not enabled 128 if (!wrapperName && nav && !nav_mob && window.innerWidth <= 768) { 129 if(incNav_DotInCont){ 130 let parentElement = document.querySelector(slidername).parentElement; 131 parentElement.querySelector('.swiper-button-prev').remove(); 132 parentElement.querySelector('.swiper-button-next').remove(); 133 delete swiperConfig.navigation; 134 }else{ 135 document.querySelector(slidername + ' .swiper-button-next').remove(); 136 document.querySelector(slidername + ' .swiper-button-prev').remove(); 137 delete swiperConfig.navigation; 138 } 139 }else if(wrapperName && nav && !nav_mob && window.innerWidth <= 768){ 140 document.querySelector(wrapperName + ' .swiper-button-next').remove(); 141 document.querySelector(wrapperName + ' .swiper-button-prev').remove(); 142 delete swiperConfig.navigation; 143 } 144 145 // Swiper initialisation 146 const swiper = new Swiper(slidername, swiperConfig); 147 148 let btnNext = document.querySelector('.wrapper ' + slidername + ' .swiper-button-next'); 149 let btnPrev = document.querySelector('.wrapper ' + slidername + ' .swiper-button-prev');
150 let containerDots = document.querySelector('.wrapper ' + slidername + ' .swiper-pagination'); 151 152 if(wrapperName){ 153 btnNext = document.querySelector('.wrapper ' + wrapperName + ' .swiper-button-next'); 154 btnPrev = document.querySelector('.wrapper ' + wrapperName + ' .swiper-button-prev'); 155 } 156 157 // Add new class on arrows 158 if ((window.innerWidth <= 768 && nav_mob && classNav) || (window.innerWidth > 768 && nav && classNav)) { 159 btnNext.classList.add(classNav); 160 btnPrev.classList.add(classNav); 161 }else if((window.innerWidth <= 768 && wrapperName && nav_mob && classNav) || (window.innerWidth > 768 && wrapperName && nav && classNav)){ 162 btnNext.classList.add(classNav); 163 btnPrev.classList.add(classNav); 164 } 165 166 // Add new class on dots 167 if ((window.innerWidth <= 768 && dots_mob && classDots) || (window.innerWidth > 768 && dots && classDots)) { 168 containerDots.classList.add(classDots); 169 } 170 171 // Return the Swiper instance 172 return swiper; 173} 174 175const btnToggleMenu = document.querySelector('.navbar-toggler'); 176const modelMenuType = document.getElementById('model-menu');
177const navbarContent = document.getElementById('navbarContent'); 178const menuStickyBlue = document.querySelector('.menu-sticky-blue'); 179 180if (btnToggleMenu && modelMenuType) { 181 btnToggleMenu.addEventListener('click', function() { 182 navbarContent.addEventListener('shown.bs.collapse', () => { 183 modelMenuType.style.zIndex = '0'; 184 if(menuStickyBlue){ 185 menuStickyBlue.style.zIndex = '0'; 186 } 187 }); 188 189 navbarContent.addEventListener('hidden.bs.collapse', () => { 190 modelMenuType.style.zIndex = '1020'; 191 if(menuStickyBlue){ 192 menuStickyBlue.style.zIndex = '1021'; 193 } 194 }); 195 }); 196} 197 198function setEqualHeight(elements) { 199 let maxHeight = 0; 200 elements.forEach(element => { 201 element.style.height = 'auto'; 202 maxHeight = Math.max(maxHeight, element.offsetHeight); 203 }); 204 205 elements.forEach(element => { 206 element.style.height = maxHeight + 'px'; 207 }); 208} 209/* custom matchheight, fuck jquery */ 210/* 211const boxes = document.querySelectorAll('.model-card'); 212window.addEventListener('load', () => setEqualHeight(Array.from(boxes))); 213window.addEventListener('resize', () => setEqualHeight(Array.from(boxes))); 214*/ 215 216function goBack() { 217 if (window.history.length > 1) { 218 window.history.back(); 219 } else { 220 window.location.href = '/'; 221 } 222} 223 224/* VALIDATE DEALERS FORM ( Telefono ) */ 225/* 226const fieldSelectors = [ 227 { selector: '#configuratore #form-test-drive #mobile', type: 'phone', labelDefault: 'Telefono*' }, 228 { selector: '#configuratore #form-test-drive #email', type: 'email', labelDefault: 'Email*' } 229]; 230*/ 231var fieldSelectors = []; 232const fields = fieldSelectors 233 .map(({ selector, type, labelDefault }) => { 234 const field = document.querySelector(selector); 235 if (field) { 236 const label = field.closest('div')?.querySelector('label'); 237 return { 238 field, 239 label, 240 type, 241 labelDefault, 242 interacted: false 243 }; 244 } 245 return null; 246 }) 247 .filter(Boolean); 248 249function validatePhone(phone) { 250 // Rimuove spazi e simbolo "+" (opzionale) 251 const cleaned = phone.replace(/\s+/g, '').replace(/^\+/, ''); 252 // Regex: solo numeri 253 const phonePattern = /^[0-9]+$/; 254 // Verifica che sia numerico e lungo almeno 10 cifre 255 const isValid = phonePattern.test(cleaned) && cleaned.length === 10; 256 return isValid; 257} 258 259function validateEmail(email) { 260 // Controlla che ci sia una @ e almeno un punto dopo 261 return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); 262} 263 264function validateForm(obj) { 265 if (!obj || !obj.field) return; 266 267 const { field, label, interacted, type, labelDefault } = obj; 268 const value = field.value.trim(); 269 let isValid = false; 270 271 if (type === 'phone') { 272 isValid = validatePhone(value); 273 } else if (type === 'email') { 274 isValid = validateEmail(value); 275 } 276 277 if (interacted && label) { 278 if (isValid) { 279 label.textContent = labelDefault; 280 label.style.color = ""; 281 field.style.border = ""; 282 field.style.backgroundColor = ""; 283 field.classList.remove('is-invalid'); 284 } else { 285 label.textContent = type === 'phone' 286 ? "Numero di telefono non valido" 287 : "Email non valida"; 288 label.style.color = "red"; 289 field.style.border = "2px solid red"; 290 field.style.backgroundColor = "#ffe6e6"; 291 field.classList.add('is-invalid'); 292 } 293 } 294} 295 296fields.forEach(obj => { 297 if (obj?.field) { 298 obj.field.addEventListener("blur", function () { 299 obj.interacted = true; 300 validateForm(obj); 301 }); 302 } 303}) 304 305// Funzione da richiamare al caricamento della pagina 306function checkGeoAndTrigger() { 307 const params = new URLSearchParams(window.location.search); 308 const geoParam = params.get("geolocation"); 309 // Controllo se il parametro è "on" 310 if (geoParam && geoParam.toLowerCase() === "on") { 311 // Controllo supporto geolocalizzazione 312 if ("geolocation" in navigator) { 313 const btn = document.querySelector(".search-container #geolocate_me"); 314 if (btn) { 315 setTimeout(() => { 316 btn.click(); 317 }, 300); 318 } 319 } else { 320 console.error("Geolocalizzazione non supportata dal browser."); 321 } 322 } 323} 324 325function scrollFieldParent(parentId) { 326 const inputField = document.getElementById(parentId); 327 if (inputField) { 328 inputField.scrollIntoView({ 329 behavior: 'smooth', 330 block: 'center' 331 }); 332 inputField.focus(); 333 } 334} 335 336// Scroll to field parent 337function scrollWrapperField(fieldName) { 338 let field = document.getElementById(fieldName); 339 if (field) { 340 field.scrollIntoView({ behavior: 'smooth', block: 'center' }); 341 // Aggiungi effetto shake 342 field.classList.add('shake'); 343 setTimeout(() => { 344 field.classList.remove('shake'); 345 }, 1500); // durata animazione 346 } else { 347 console.warn('Elemento non trovato:', fieldName); 348 } 349}
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.