1// Add geolocation for Gravity Forms. Added by Eyal.W 14.01.2025 | Changed 15.01.2025 2 3// Create mutation observer to detect when form loads in popup 4 const formIds = [11, 13, 14, 15]; 5 6const observer = new MutationObserver((mutations, obs) => { 7 formIds.forEach(formId => { 8 const formWrapper = document.getElementById('gform_wrapper_' + formId); 9 10 if (formWrapper) { 11 obs.disconnect(); 12 initGeolocation(formWrapper); 13 } 14 }); 15}); 16 17// Start observing when popup opens 18jQuery(document).on('elementor/popup/show', function() { 19 observer.observe(document.body, { 20 childList: true, 21 subtree: true 22 }); 23}); 24 25function initGeolocation(formWrapper) { 26 const fields = { 27 address: formWrapper.querySelector('input[name="input_20"]'), 28 latitude: formWrapper.querySelector('input[name="input_27"]'), 29 longitude: formWrapper.querySelector('input[name="input_28"]'), 30 country: formWrapper.querySelector('input[name="input_29"]') 31 }; 32 33 if (!Object.values(fields).every(field => field)) return; 34 35 if (navigator.geolocation) { 36 navigator.geolocation.getCurrentPosition( 37 function(position) { 38 const { latitude, longitude } = position.coords; 39 40 fields.latitude.value = latitude; 41 fields.longitude.value = longitude; 42 43 fetch(`https://nominatim.openstreetmap.org/reverse?format=json&lat=${latitude}&lon=${longitude}&addressdetails=1`) 44 .then(response => response.json()) 45 .then(data => { 46 if (data?.address) { 47 fields.address.value = data.display_name; 48 fields.country.value = data.address.country; 49 } else { 50 handleError('Address not found', fields); 51 } 52 }) 53 .catch(() => handleError('Unable to fetch address', fields)); 54 }, 55 () => handleError('Location detection failed', fields) 56 ); 57 } else { 58 handleError('Geolocation not supported', fields); 59 } 60} 61 62function handleError(message, fields) { 63 Object.values(fields).forEach(field => { 64 field.value = message + '. Please enter manually.'; 65 }); 66} 67 68// Displaying nearest Locations based on Latitude and Longitude - Add by EYAL.W 15.01.2025 69 70document.addEventListener('DOMContentLoaded', function () { 71 // Array of form IDs to apply the script to 72 const formIds = [11, 13, 14, 15]; 73 74 formIds.forEach(formId => { 75 const formWrapper = document.querySelector(`#gform_wrapper_${formId}`); 76 77 if (!formWrapper) { 78 console.error(`Form wrapper for form ID ${formId} not found. Skipping.`); 79 return; 80 } 81 82 const addressField = formWrapper.querySelector('input[name="input_20"]'); 83 const latitudeField = formWrapper.querySelector('input[name="input_27"]'); 84 const longitudeField = formWrapper.querySelector('input[name="input_28"]'); 85 const selectField30 = formWrapper.querySelector('select[name="input_30"]'); 86 const field31 = formWrapper.querySelector('input[name="input_36"]'); 87 const field32 = formWrapper.querySelector('input[name="input_37"]'); 88 const field33 = formWrapper.querySelector('input[name="input_38"]'); 89 const field46 = formWrapper.querySelector('input[name="input_46"]'); // Added field 46 90 91 if (!addressField || !latitudeField || !longitudeField || !selectField30 || !field31 || !field32 || !field33 || !field46) { 92 console.error(`One or more required fields are missing within form ${formId}.`); 93 return; 94 } 95 96 let selectedCountry = ''; 97 98 function populateNearestLocations(latitude, longitude) { 99 const url = 'https://helendoron.com/respone_loc.json'; 100 101 fetch(url) 102 .then(response => response.json()) 103 .then(locations => { 104 function haversine_distance(lat1, lon1, lat2, lon2) { 105 const earth_radius = 6371; 106 const lat_diff = (lat2 - lat1) * Math.PI / 180; 107 const lon_diff = (lon2 - lon1) * Math.PI / 180; 108 const a = Math.sin(lat_diff / 2) ** 2 + 109 Math.cos(lat1 * Math.PI / 180) * 110 Math.cos(lat2 * Math.PI / 180) * 111 Math.sin(lon_diff / 2) ** 2; 112 const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 113 return earth_radius * c; 114 } 115 116 const distances = locations.map(location => ({ 117 fullAddress: `${location.BillingStreet}
117, ${location.BillingCity}`, 118 distance: haversine_distance(latitude, longitude, location.BillingLatitude, location.BillingLongitude), 119 userId: location.UserId__c || '', // Get UserId__c value 120 mfUserId: location.MF_USER_ID__c || '' // Added MF_USER_ID__c value 121 })); 122 123 const filteredLocations = distances.filter(location => location.distance <= 25); 124 const nearestLocations = filteredLocations.sort((a, b) => a.distance - b.distance).slice(0, 3); 125 126 // Clear existing options in the select field 127 selectField30.innerHTML = ''; 128 129 // Populate the select field with the nearest locations 130 nearestLocations.forEach(location => { 131 const option = document.createElement('option'); 132 option.value = location.userId; // Use UserId__c as the value 133 option.textContent = location.fullAddress; 134 selectField30.appendChild(option); 135 }); 136 137 if (nearestLocations.length === 0) { 138 const noLocationOption = document.createElement('option'); 139 noLocationOption.value = 'no_locations'; 140 noLocationOption.textContent = 'No locations within 30 km'; 141 selectField30.appendChild(noLocationOption); 142 } 143 144 const otherOption = document.createElement('option'); 145 otherOption.value = 'other'; 146 otherOption.textContent = 'Other'; 147 selectField30.appendChild(otherOption); 148 149 // Update nearest locations in the additional fields with UserId__c values 150 field31.value = nearestLocations[0] ? nearestLocations[0].userId : 'N/A'; 151 field32.value = nearestLocations[1] ? nearestLocations[1].userId : 'N/A'; 152 field33.value = nearestLocations[2] ? nearestLocations[2].userId : 'N/A'; 153 154 // Populate field 46 with the first location's MF_USER_ID__c value 155 field46.value = nearestLocations[0] ? nearestLocations[0].mfUserId : 'N/A'; 156 }) 157 .catch(error => { 158 console.error("Error fetching or processing JSON data:", error); 159 selectField30.innerHTML = ''; 160 const errorOption = document.createElement('option'); 161 errorOption.value = 'error'; 162 errorOption.textContent = 'Error loading data'; 163 selectField30.appendChild(errorOption); 164 165 field31.value = "Error loading data"; 166 field32.value = "Error loading data"; 167 field33.value = "Error loading data"; 168 field46.value = "Error loading data"; // Added error handling for field 46 169 }); 170 } 171 172 // Add click event listener to address field 173 addressField.addEventListener('click', function() { 174 this.value = ''; // Clear the field when clicked 175 }); 176 177 // Initialize Google Maps Autocomplete 178 function initAutocomplete() { 179 const autocomplete = new google.maps.places.Autocomplete(addressField, { 180 types: ['geocode'], 181 }); 182 183 autocomplete.addListener('place_changed', function () { 184 const place = autocomplete.getPlace(); 185 186 if (place.geometry) { 187 const latitude = place.geometry.location.lat(); 188 const longitude = place.geometry.location.lng(); 189 190 const countryComponent = place.address_components.find(component => 191 component.types.includes('country') 192 ); 193 if (countryComponent) { 194 selectedCountry = countryComponent.long_name; 195 } 196 197 latitudeField.value = latitude; 198 longitudeField.value = longitude; 199 200 populateNearestLocations(latitude, longitude); 201 } 202 }); 203 } 204 205 // Initialize geolocation 206 function initializeGeolocation() { 207 if (navigator.geolocation) { 208 navigator.geolocation.getCurrentPosition( 209 function (position) { 210 const latitude = position.coords.latitude; 211 const longitude = position.coords.longitude; 212 213 latitudeField.value = latitude; 214 longitudeField.value = longitude; 215 216 getCountryFromCoordinates(latitude, longitude) 217 .then(() => { 218 populateNearestLocations(latitude, longitude); 219 }) 220 .catch(error => { 221 console.error("Error getting country:", error); 222 }); 223 }, 224 function (error) { 225 console.error("Geolocation error:", error); 226 } 227 ); 228 } 229 } 230 231 // Get country from coordinates 232 function getCountryFromCoordinates(latitude, longitude) { 233 const geocoder = new google.maps.Geocoder(); 234 const latlng = { lat: parseFloat(latitude), lng: parseFloat(longitude) }; 235 236 return new Promise((resolve, reject) => { 237 geocoder.geocode({ location: latlng }, (results, status) => { 238 if (status === google.maps.GeocoderStatus.OK) { 239 if (results[0]) { 240 const countryComponent = results[0].address_components.find(component => 241 component.types.includes('country') 242 ); 243 if (countryComponent) { 244 selectedCountry = countryComponent.long_name; 245 addressField.value = results[0].formatted_address; 246 resolve(countryComponent.long_name); 247 } else { 248 reject('No country found'); 249 } 250 } else { 251 reject('No results found'); 252 } 253 } else { 254 reject('Geocoder failed: ' + status); 255 } 256 }); 257 }); 258 } 259 260 // Initialize the functionality 261 initAutocomplete(); 262 initializeGeolocation(); 263 }); 264}); 265 266//Populate OTHER as Conditional Logic - Added by Eyal.W - 19-01-2025 267 268document.addEventListener('DOMContentLoaded', function() { 269 // Array of form IDs to apply the dropdown script to 270 const formIds = [11, 13, 14, 15]; 271 272 formIds.forEach(formId => { 273 const formWrapper = document.querySelector(`#gform_wrapper_${formId}`); 274 275 if (!formWrapper) { 276 console.error(`Form wrapper for form ${formId} not found. Skipping.`); 277 return; 278 } 279 280 // Get the dropdown elements within this specific form 281 const countryDropdown = formWrapper.querySelector('.countries-dropdown select'); 282 const cityDropdown = formWrapper.querySelector('.cities-dropdown select'); 283 const centerDropdown = formWrapper.querySelector('.centers-dropdown select'); 284 285 if (!countryDropdown || !cityDropdown || !centerDropdown) { 286 console.error(`Dropdowns not found in form ${formId}`); 287 return; 288 } 289 290 // Disable city and center dropdowns initially 291 cityDropdown.disabled = true; 292 centerDropdown.disabled = true; 293 294 // Fetch locations data 295 fetch('https://helendoron.com/respone_loc.json') 296 .then(response => response.json()) 297 .then(data => { 298 // Process the data and organize by country/city 299 const locations = processLocations(data); 300 setupDropdowns(locations, countryDropdown, cityDropdown, centerDropdown); 301 }) 302 .catch(error => console.error('Error fetching locations:', error)); 303 }); 304 305 function processLocations(data) { 306 const locations = { 307 countries: new Set(), 308 cities: {}, 309 centers: {} 310 }; 311 312 data.forEach(location => {
313 const country = location.BillingCountry; 314 const city = location.BillingCity; 315 const center = { 316 name: location.Name, 317 address: location.BillingStreet, 318 email: location.Email__c, 319 phone: location.Phone, 320 userId: location.UserId__c 321 }; 322 323 locations.countries.add(country); 324 325 if (!locations.cities[country]) { 326 locations.cities[country] = new Set(); 327 } 328 locations.cities[country].add(city); 329 330 const cityKey = `${country}-${city}`; 331 if (!locations.centers[cityKey]) { 332 locations.centers[cityKey] = []; 333 } 334 locations.centers[cityKey].push(center); 335 }); 336 337 return locations; 338 } 339 340 function setupDropdowns(locations, countryDropdown, cityDropdown, centerDropdown) { 341 // Populate country dropdown 342 populateCountries(locations.countries, countryDropdown); 343 344 // Add event listeners 345 countryDropdown.addEventListener('change', () => { 346 const selectedCountry = countryDropdown.value; 347 if (selectedCountry) { 348 cityDropdown.disabled = false; 349 populateCities(locations.cities[selectedCountry] || [], cityDropdown); 350 } else { 351 cityDropdown.disabled = true; 352 centerDropdown.disabled = true; 353 resetDropdown(cityDropdown, 'City'); 354 resetDropdown(centerDropdown, 'Center'); 355 } 356 }); 357 358 cityDropdown.addEventListener('change', () => { 359 const selectedCountry = countryDropdown.value; 360 const selectedCity = cityDropdown.value; 361 if (selectedCity) { 362 centerDropdown.disabled = false; 363 const cityKey = `${selectedCountry}-${selectedCity}`; 364 populateCenters(locations.centers[cityKey] || [], centerDropdown); 365 } else { 366 centerDropdown.disabled = true; 367 resetDropdown(centerDropdown, 'Center'); 368 } 369 }); 370 } 371 372 function populateCountries(countries, dropdown) { 373 resetDropdown(dropdown, 'Country'); 374 Array.from(countries).sort().forEach(country => { 375 const option = document.createElement('option'); 376 option.value = country; 377 option.text = country; 378 dropdown.appendChild(option); 379 }); 380 } 381 382 function populateCities(cities, dropdown) { 383 resetDropdown(dropdown, 'City'); 384 Array.from(cities).sort().forEach(city => { 385 const option = document.createElement('option'); 386 option.value = city; 387 option.text = city; 388 dropdown.appendChild(option); 389 }); 390 } 391 392 function populateCenters(centers, dropdown) { 393 resetDropdown(dropdown, 'Center'); 394 centers.sort((a, b) => a.name.localeCompare(b.name)).forEach(center => { 395 const option = document.createElement('option'); 396 option.value = center.userId; 397 option.text = `${center.name} - ${center.address}`; 398 option.setAttribute('data-email', center.email); 399 option.setAttribute('data-phone', center.phone); 400 dropdown.appendChild(option); 401 }); 402 } 403 404 function resetDropdown(dropdown, type) { 405 dropdown.innerHTML = ''; 406 const defaultOption = document.createElement('option'); 407 defaultOption.value = ''; 408 defaultOption.text = `Select ${type}`; 409 dropdown.appendChild(defaultOption); 410 } 411}); 412 413 414// Added 26.01.2025 by Eyal.W 415 416 417jQuery(document).ready(function($) { 418 // Initialize script when popup opens 419 $(document).on('elementor/popup/show', (event, id, instance) => { 420 const formIds = [11, 13, 14, 15]; 421 const popupElement = instance.$element[0]; 422 423 formIds.forEach(formId => { 424 const formWrapper = popupElement.querySelector(`#gform_wrapper_${formId}`); 425 if (!formWrapper) return; 426 427 initializeForm(formWrapper, formId); 428 }); 429 }); 430 431 function initializeForm(formWrapper, formId) { 432 const addressField = formWrapper.querySelector('input[name="input_20"]'); 433 const latitudeField = formWrapper.querySelector('input[name="input_27"]'); 434 const longitudeField = formWrapper.querySelector('input[name="input_28"]'); 435 const selectField30 = formWrapper.querySelector('select[name="input_30"]'); 436 const field31 = formWrapper.querySelector('input[name="input_36"]'); 437 const field32 = formWrapper.querySelector('input[name="input_37"]'); 438 const field33 = formWrapper.querySelector('input[name="input_38"]'); 439 const field46 = formWrapper.querySelector('input[name="input_46"]'); 440 441 if (!addressField || !latitudeField || !longitudeField || !selectField30 || 442 !field31 || !field32 || !field33 || !field46) return; 443 444 // Rest of your existing functions 445 function populateNearestLocations(latitude, longitude) { 446 fetch('https://helendoron.com/respone_loc.json') 447 .then(response => response.json()) 448 .then(locations => { 449 function haversine_distance(lat1, lon1, lat2, lon2) { 450 const earth_radius = 6371; 451 const lat_diff = (lat2 - lat1) * Math.PI / 180; 452 const lon_diff = (lon2 - lon1) * Math.PI / 180; 453 const a = Math.sin(lat_diff / 2) ** 2 + 454 Math.cos(lat1 * Math.PI / 180) * 455 Math.cos(lat2 * Math.PI / 180) * 456 Math.sin(lon_diff / 2) ** 2; 457 return 2 * earth_radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 458 } 459 460 const distances = locations.map(location => ({ 461 fullAddress: `${location.BillingStreet}
461, ${location.BillingCity}`, 462 distance: haversine_distance(latitude, longitude, 463 location.BillingLatitude, location.BillingLongitude), 464 userId: location.UserId__c || '', 465 mfUserId: location.MF_USER_ID__c || '' 466 })); 467 468 const filteredLocations = distances.filter(loc => loc.distance <= 25); 469 const nearestLocations = filteredLocations 470 .sort((a, b) => a.distance - b.distance) 471 .slice(0, 3); 472 473 updateSelectField(nearestLocations); 474 updateHiddenFields(nearestLocations); 475 }) 476 .catch(handleError); 477 } 478 479 function updateSelectField(locations) { 480 selectField30.innerHTML = ''; 481 482 locations.forEach(location => { 483 const option = document.createElement('option'); 484 option.value = location.userId; 485 option.textContent = location.fullAddress; 486 selectField30.appendChild(option); 487 }); 488 489 if (locations.length === 0) { 490 selectField30.appendChild(createOption('', 'No locations within 30 km')); 491 } 492 493 selectField30.appendChild(createOption('other', 'Other')); 494 } 495 496 function updateHiddenFields(locations) { 497 field31.value = locations[0]?.userId || 'N/A'; 498 field32.value = locations[1]?.userId || 'N/A'; 499 field33.value = locations[2]?.userId || 'N/A'; 500 field46.value = locations[0]?.mfUserId || 'N/A'; 501 } 502 503 function handleError(error) { 504 console.error("Error:", error); 505 selectField30.innerHTML = ''; 506 selectField30.appendChild(createOption('error', 'Error loading data')); 507 508 [field31, field32, field33, field46].forEach(field => { 509 field.value = "Error loading data"; 510 }); 511 } 512 513 function createOption(value, text) { 514 const option = document.createElement('option'); 515 option.value = value; 516 option.textContent = text; 517 return option; 518 } 519 520 // Initialize Google Maps Autocomplete 521 const autocomplete = new google.maps.places.Autocomplete(addressField, { 522 types: ['geocode'] 523 }); 524 525 autocomplete.addListener('place_changed', () => { 526 const place = autocomplete.getPlace(); 527 if (!place.geometry) return; 528 529 const latitude = place.geometry.location.lat(); 530 const longitude = place.geometry.location.lng(); 531 532 latitudeField.value = latitude; 533 longitudeField.value = longitude; 534 populateNearestLocations(latitude, longitude); 535 }); 536 537 // Initialize geolocation 538 if (navigator.geolocation) { 539 navigator.geolocation.getCurrentPosition( 540 position => { 541 const { latitude, longitude } = position.coords; 542 latitudeField.value = latitude; 543 longitudeField.value = longitude; 544 545 const geocoder = new google.maps.Geocoder(); 546 geocoder.geocode({ location: { lat: latitude, lng: longitude } }, 547 (results, status) => { 548 if (status === google.maps.GeocoderStatus.OK && results[0]) { 549 addressField.value = results[0].formatted_address; 550 populateNearestLocations(latitude, longitude); 551 } 552 } 553 ); 554 }, 555 error => console.error("Geolocation error:", error) 556 ); 557 } 558 559 // Setup conditional logic for other fields 560 const field3Container = formWrapper.querySelector(`#field_${formId}_3`).closest('.gfield'); 561 const field4Container = formWrapper.querySelector(`#field_${formId}_4`).closest('.gfield'); 562 const field5Container = formWrapper.querySelector(`#field_${formId}_5`).closest('.gfield'); 563 564 function toggleFields() { 565 const shouldShow = selectField30.value === 'other'; 566 [field3Container, field4Container, field5Container].forEach(container => { 567 container.style.display = shouldShow ? 'block' : 'none'; 568 }); 569 } 570 571 toggleFields(); 572 selectField30.addEventListener('change', toggleFields); 573 addressField.addEventListener('click', () => addressField.value = ''); 574 } 575}); 576 577//Hide Other Fields by deafult - Conditional Logic to show when Nearest location select is Other - Added by Eyal.W 20.1.2025 578 579document.addEventListener('DOMContentLoaded', function () {
580 [3, 6, 7].forEach(formId => { 581 const formWrapper = document.querySelector(`#gform_wrapper_${formId}`); 582 583 if (!formWrapper) { 584 console.error(`Form wrapper for form ${formId} not found.`); 585 return; 586 } 587 588 const selectField30 = formWrapper.querySelector('select[name="input_30"]'); 589 const field3Container = formWrapper.querySelector(`#field_${formId}_3`).closest('.gfield'); 590 const field4Container = formWrapper.querySelector(`#field_${formId}_4`).closest('.gfield'); 591 const field5Container = formWrapper.querySelector(`#field_${formId}_5`).closest('.gfield'); 592 593 function toggleFields() { 594 const shouldShow = selectField30.value === 'other'; 595 const displayValue = shouldShow ? 'block' : 'none'; 596 597 field3Container.style.display = displayValue; 598 field4Container.style.display = displayValue; 599 field5Container.style.display = displayValue; 600 } 601 602 toggleFields(); 603 selectField30.addEventListener('change', toggleFields); 604 }); 605}); 606 607// Adde by Eyal.w - Popup enable Other - 26.01.2025 608 609jQuery(document).ready(function($) { 610 $(document).on('elementor/popup/show', (event, id, instance) => { 611 const formIds = [11, 13, 14, 15]; 612 const popupElement = instance.$element[0]; 613 614 formIds.forEach(formId => initializeDropdowns(formId, popupElement)); 615 }); 616 617 function initializeDropdowns(formId, popupElement) { 618 const formWrapper = popupElement.querySelector(`#gform_wrapper_${formId}`); 619 if (!formWrapper) return; 620 621 const dropdowns = { 622 country: formWrapper.querySelector('.countries-dropdown select'), 623 city: formWrapper.querySelector('.cities-dropdown select'), 624 center: formWrapper.querySelector('.centers-dropdown select') 625 }; 626 627 if (!dropdowns.country || !dropdowns.city || !dropdowns.center) return; 628 629 dropdowns.city.disabled = true; 630 dropdowns.center.disabled = true; 631 632 fetch('https://helendoron.com/respone_loc.json') 633 .then(response => response.json()) 634 .then(data => setupDropdowns(processLocations(data), dropdowns)) 635 .catch(error => console.error('Error:', error)); 636 } 637 638 function processLocations(data) { 639 const locations = { 640 countries: new Set(), 641 cities: {}, 642 centers: {} 643 }; 644 645 data.forEach(location => { 646 const country = location.BillingCountry; 647 const city = location.BillingCity; 648 const center = { 649 name: location.Name, 650 address: location.BillingStreet, 651 email: location.Email__c, 652 phone: location.Phone, 653 userId: location.UserId__c 654 }; 655 656 locations.countries.add(country); 657 if (!locations.cities[country]) locations.cities[country] = new Set(); 658 locations.cities[country].add(city); 659 660 const cityKey = `${country}-${city}`; 661 if (!locations.centers[cityKey]) locations.centers[cityKey] = []; 662 locations.centers[cityKey].push(center); 663 }); 664 665 return locations; 666 } 667 668 function setupDropdowns(locations, dropdowns) { 669 populateDropdown(dropdowns.country, Array.from(locations.countries), 'Country'); 670 671 dropdowns.country.addEventListener('change', () => { 672 const selectedCountry = dropdowns.country.value; 673 dropdowns.city.disabled = !selectedCountry; 674 675 if (selectedCountry) { 676 populateDropdown(dropdowns.city, Array.from(locations.cities[selectedCountry] || []), 'City'); 677 } else { 678 resetDropdowns(dropdowns); 679 } 680 }); 681 682 dropdowns.city.addEventListener('change', () => { 683 const selectedCity = dropdowns.city.value; 684 dropdowns.center.disabled = !selectedCity; 685 686 if (selectedCity) { 687 const cityKey = `${dropdowns.country.value}-${selectedCity}`; 688 populateDropdown(dropdowns.center, locations.centers[cityKey] || [], 'Center', true); 689 } else { 690 resetDropdown(dropdowns.center, 'Center'); 691 } 692 }); 693 } 694 695 function populateDropdown(dropdown, items, type, isCenters = false) { 696 resetDropdown(dropdown, type); 697 const sortedItems = isCenters ? items.sort((a, b) => a.name.localeCompare(b.name)) : Array.from(items).sort(); 698
699 sortedItems.forEach(item => { 700 const option = document.createElement('option'); 701 if (isCenters) { 702 option.value = item.userId; 703 option.textContent = `${item.name} - ${item.address}`; 704 option.dataset.email = item.email; 705 option.dataset.phone = item.phone; 706 } else { 707 option.value = item; 708 option.textContent = item; 709 } 710 dropdown.appendChild(option); 711 }); 712 } 713 714 function resetDropdown(dropdown, type) { 715 dropdown.innerHTML = `<option value="">${type}</option>`; 716 } 717 718 function resetDropdowns(dropdowns) { 719 dropdowns.city.disabled = true; 720 dropdowns.center.disabled = true; 721 resetDropdown(dropdowns.city, 'City'); 722 resetDropdown(dropdowns.center, 'Center'); 723 } 724}); 725 726 727//Disable submit by clicking Enter on Gravity Forms Added by Eyal.W on 20.1.2025 728 729jQuery(document).ready(function($) { 730 // Target all Gravity Forms 731 $('.gform_wrapper form').on('keypress', function(event) { 732 // Check if Enter key was pressed (key code 13) 733 if (event.keyCode === 13 || event.which === 13) { 734 // Allow Enter key in textarea fields 735 if (event.target.tagName.toLowerCase() !== 'textarea') { 736 event.preventDefault(); 737 return false; 738 } 739 } 740 }); 741 742 743//Autocmomplete message 744formIds.forEach(formId => { 745 function initAddressValidation(scope = document) { 746 const form = $(scope).find(`#gform_${formId}`); 747 if (!form.length) return; 748 749 const addressField = form.find('input[name="input_20"]'); 750 const latitudeField = form.find('input[name="input_27"]'); 751 const longitudeField = form.find('input[name="input_28"]'); 752 const selectField30 = form.find('select[name="input_30"]'); 753 if (!addressField.length) return; 754 755 const warningDiv = $('<div class="address-warning" style="color: red; margin-top: 5px; text-align: left; font-size: 14px; background-color: rgba(255, 255, 255, 0.8); padding: 5px 10px; border-radius: 4px;">Please select an address from the suggestions list </div>'); 756 addressField.parent().append(warningDiv); 757 warningDiv.hide(); 758 759 let selectedAddress = ''; 760 761 if (typeof google !== 'undefined' && google.maps) { 762 const autocomplete = new google.maps.places.Autocomplete(addressField[0]); 763 autocomplete.addListener('place_changed', function() { 764 const place = autocomplete.getPlace(); 765 if (place && place.formatted_address) { 766 selectedAddress = place.formatted_address; 767 warningDiv.hide(); 768 addressField.css('border-color', ''); 769 770 if (place.geometry) { 771 const latitude = place.geometry.location.lat(); 772 const longitude = place.geometry.location.lng(); 773 latitudeField.val(latitude); 774 longitudeField.val(longitude); 775 776 // Fetch and update nearest locations 777 fetch('https://helendoron.com/respone_loc.json') 778 .then(response => response.json()) 779 .then(locations => { 780 function haversine_distance(lat1, lon1, lat2, lon2) { 781 const earth_radius = 6371; 782 const lat_diff = (lat2 - lat1) * Math.PI / 180; 783 const lon_diff = (lon2 - lon1) * Math.PI / 180; 784 const a = Math.sin(lat_diff / 2) ** 2 + 785 Math.cos(lat1 * Math.PI / 180) * 786 Math.cos(lat2 * Math.PI / 180) * 787 Math.sin(lon_diff / 2) ** 2; 788 return 2 * earth_radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); 789 } 790 791 const distances = locations.map(location => ({ 792 fullAddress: `${location.BillingStreet}
792, ${location.BillingCity}`, 793 distance: haversine_distance(latitude, longitude, 794 location.BillingLatitude, location.BillingLongitude), 795 userId: location.UserId__c || '', 796 mfUserId: location.MF_USER_ID__c || '' 797 })); 798 799 const filteredLocations = distances.filter(loc => loc.distance <= 25); 800 const nearestLocations = filteredLocations 801 .sort((a, b) => a.distance - b.distance) 802 .slice(0, 3); 803 804 // Update select field options 805 selectField30.empty(); 806 nearestLocations.forEach(location => { 807 selectField30.append($('<option>', { 808 value: location.userId, 809 text: location.fullAddress 810 })); 811 }); 812 813 if (nearestLocations.length === 0) { 814 selectField30.append($('<option>', { 815 value: '', 816 text: 'No locations within 30 km' 817 })); 818 } 819 820 selectField30.append($('<option>', { 821 value: 'other', 822 text: 'Other' 823 })); 824 825 // Update hidden fields 826 form.find('input[name="input_36"]').val(nearestLocations[0]?.userId || 'N/A'); 827 form.find('input[name="input_37"]').val(nearestLocations[1]?.userId || 'N/A'); 828 form.find('input[name="input_38"]').val(nearestLocations[2]?.userId || 'N/A'); 829 form.find('input[name="input_46"]').val(nearestLocations[0]?.mfUserId || 'N/A'); 830 }) 831 .catch(error => { 832 console.error("Error:", error); 833 selectField30.empty().append($('<option>', { 834 value: 'error', 835 text: 'Error loading data' 836 })); 837 }); 838 } 839 } 840 }); 841 } 842 843 addressField.on('input', function() { 844 if (addressField.val() !== selectedAddress) { 845 warningDiv.show(); 846 addressField.css('border-color', 'red'); 847 } 848 }); 849 850 $(document).on('gform_post_render', function() { 851 form.on('submit', function(e) { 852 if (addressField.val() !== selectedAddress) { 853 e.preventDefault(); 854 warningDiv.show(); 855 addressField.css('border-color', 'red'); 856 return false; 857 } 858 return true; 859 }); 860 }); 861 } 862 863 // Initialize for regular page forms 864 $(document).ready(function() { 865 initAddressValidation(); 866 }); 867 868 // Initialize for popup forms 869 $(document).on('elementor/popup/show', function(event, id, instance) { 870 initAddressValidation(instance.$element[0]); 871 }); 872}); 873 874});
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.