1document.addEventListener('DOMContentLoaded', function () { 2 // Init datepickers 3 const datepickers = document.querySelectorAll('.dd-enquiry-form__datepicker'); 4 datepickers.forEach(input => { 5 input.type = 'date'; 6 input.addEventListener('change', function () { 7 const date = new Date(this.value); 8 if (!isNaN(date.getTime())) { 9 const day = date.getDate(); 10 const month = date.toLocaleDateString('en-GB', { month: 'short' }); 11 const year = date.getFullYear().toString().slice(-2); 12 const formattedDate = `${day} ${month}, ${year}`; 13 this.setAttribute('data-formatted', formattedDate); 14 } 15 }); 16 }); 17 18 // Function to handle venue selection change 19 function handleVenueChange(selectElement) { 20 // Don't process if no value is selected 21 if (!selectElement.value || selectElement.value === '') { 22 return; 23 } 24 25 const [subvenueVal = '', venueVal = ''] = selectElement.value.split(':'); 26 const form = selectElement.closest('form') || document; 27 const subvenueInput = form.querySelector('input[name="subvenue"]'); 28 const venueInput = form.querySelector('input[name="venue"]'); 29 const eventTypeSelect = form.querySelector('select[name="type_of_event"]'); 30 31 if (subvenueInput) { 32 subvenueInput.value = subvenueVal; 33 } 34 if (venueInput) { 35 venueInput.value = venueVal; 36 } 37 38 // Update event types dropdown based on selected venue 39 if (eventTypeSelect && typeof evolvEnquiryForms !== 'undefined' && evolvEnquiryForms.venues) { 40 // Try exact match first, then trimmed match 41 let selectedVenue = evolvEnquiryForms.venues.find(venue => venue.value === selectElement.value); 42 if (!selectedVenue) { 43 // Try with trimmed values 44 selectedVenue = evolvEnquiryForms.venues.find( 45 venue => venue.value.trim() === selectElement.value.trim(), 46 ); 47 } 48 49 if (selectedVenue && selectedVenue.event_types && selectedVenue.event_types.length > 0) { 50 // Store current selection if it exists 51 const currentValue = eventTypeSelect.value; 52 53 // Clear existing options 54 eventTypeSelect.innerHTML = ''; 55 56 // Add default option 57 const defaultOption = document.createElement('option'); 58 defaultOption.value = ''; 59 defaultOption.textContent = 'Please select'; 60 defaultOption.disabled = true; 61 defaultOption.selected = !currentValue || currentValue === ''; 62 eventTypeSelect.appendChild(defaultOption); 63 64 // Add event type options 65 selectedVenue.event_types.forEach(eventType => { 66 const option = document.createElement('option'); 67 option.value = eventType; 68 option.textContent = eventType; 69 // Preserve selection if it matches 70 if (currentValue === eventType) { 71 option.selected = true; 72 defaultOption.selected = false; 73 } 74 eventTypeSelect.appendChild(option); 75 }); 76 } 77 } 78 } 79 80 // Handle original venue select (blog ID 31) 81 const venueSelects = document.querySelectorAll('.js-venue-select'); 82 venueSelects.forEach(select => { 83 select.addEventListener('change', function () { 84 handleVenueChange(this); 85 }); 86 87 // Trigger change on page load if a venue is already selected 88 if (select.value) { 89 handleVenueChange(select); 90 } 91 }); 92 93 // Handle additional venue select 94 const additionalVenueSelects = document.querySelectorAll('.js-additional-venue-select'); 95 additionalVenueSelects.forEach(select => { 96 select.addEventListener('change', function () { 97 handleVenueChange(this); 98 }); 99 100 // Trigger change on page load if a venue is already selected 101 if (select.value && select.value !== '') { 102 handleVenueChange(select); 103 } 104 }); 105 106 // Attach to all buttons with class dd-enquiry-form__submit 107 const submitButtons = document.querySelectorAll('.dd-enquiry-form__submit'); 108 109 submitButtons.forEach(button => { 110 // Prevent duplicate event listeners 111 if (button.dataset.listenerAttached === 'true') return; 112 button.dataset.listenerAttached = 'true'; 113 114 button.addEventListener('click', e => { 115 e.preventDefault(); 116 117 const form = button.closest('.dd-enquiry-form'); 118 if (!form) return; 119 120 // Prevent multiple submissions 121 if (button.disabled || button.dataset.submitting === 'true') return; 122 button.dataset.submitting = 'true'; 123 button.disabled = true; 124 125 // Reset messages just for this form 126 form.querySelectorAll('.dd-enquiry-form__message').forEach(msg => msg.remove()); 127 128 if (!form.checkValidity()) { 129 // Find the first invalid field 130 const firstInvalid = form.querySelector(':invalid'); 131 132 // Create an accessible error message 133 let msg = firstInvalid.nextElementSibling; 134 if (!msg || !msg.classList.contains('dd-enquiry-form__message')) { 135 msg = document.createElement('span'); 136 msg.style.color = 'red'; 137 msg.style.fontSize = '12px'; 138 msg.classList.add('dd-enquiry-form__message', 'f__paragraph-regular'); 139 msg.setAttribute('role', 'alert'); // screen readers will announce this 140 firstInvalid.after(msg); 141 } 142 143 // Set a descriptive message 144 if (firstInvalid.validity.valueMissing) { 145 msg.textContent = `Please enter your ${firstInvalid.name.replace('_', ' ')}.`; 146 } else if (firstInvalid.validity.typeMismatch) { 147 msg.textContent = `Please enter a valid ${firstInvalid.type}.`; 148 } else { 149 msg.textContent = `Please correct this field.`; 150 } 151 152 // Focus the first invalid field 153 firstInvalid.focus(); 154 155 // Re-enable the button since validation failed 156 button.disabled = false;
157 button.dataset.submitting = 'false'; 158 return; 159 } 160 161 const formData = new FormData(form); 162 163 // Debug log 164 for (const pair of formData.entries()) { 165 console.log(`${pair[0]}, ${pair[1]}`); 166 } 167 168 // GA event tracking 169 const eventTypeElem = form.querySelector('select[name="type_of_event"]'); 170 if (eventTypeElem) { 171 const eventType = eventTypeElem.value; 172 const eventTypeGaName = `enquiry_${eventType.replace(/ /g, '_').toLowerCase()}`; 173 174 window.dataLayer = window.dataLayer || []; 175 window.dataLayer.push({ event: eventTypeGaName }); 176 console.log('Event pushed to dataLayer:', eventTypeGaName); 177 } 178 179 // Send via fetch 180 fetch(evolvEnquiryForms.ajaxUrl, { 181 method: 'POST', 182 body: formData, 183 }) 184 .then(response => response.text()) 185 .then(data => { 186 if (data.indexOf('Your request has been queued') !== -1) { 187 form.style.display = 'none'; 188 const p = document.createElement('p'); 189 p.classList.add('dd-enquiry-form__message', 'f__paragraph-regular', 'text-center'); 190 p.innerHTML = 'Thank you for your enquiry. A member of the team will be in touch soon.'; 191 form.after(p); 192 // Keep button disabled on success 193 } else { 194 const p = document.createElement('p'); 195 p.classList.add('dd-enquiry-form__message', 'f__paragraph-regular', 'text-center'); 196 p.innerHTML = 197 'Sorry, there was a problem sending your enquiry. Please get in touch via the contact page or try again later.'; 198 form.after(p); 199 // Re-enable button on error so user can retry 200 button.disabled = false; 201 button.dataset.submitting = 'false'; 202 } 203 }) 204 .catch(error => { 205 console.error(error); 206 // Re-enable button on error so user can retry 207 button.disabled = false; 208 button.dataset.submitting = 'false'; 209 }); 210 }); 211 }); 212});
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.