1/** 2 * Submit a prizedraw form via AJAX 3 */ 4jQuery(function($){ // use jQuery code inside this to avoid "$ is not defined" error 5 6 // --- Helpers --- 7 function normaliseDigits(str) { 8 return (str || '').replace(/\D+/g, ''); 9 } 10 11 function isValidPhone(phone) { 12 // Accept numbers, spaces and common punctuation; require 10â15 digits total 13 if (!phone) return false; 14 var digits = normaliseDigits(phone); 15 if (digits.length < 10 || digits.length > 15) return false; 16 // Basic sanity: only allowed chars overall 17 return /^[0-9()+\-\s]+$/.test(phone); 18 } 19 20 function isValidDOB(dobStr) { 21 if (!dobStr) return false; 22 var d = new Date(dobStr); 23 if (isNaN(d.getTime())) return false; 24 var today = new Date(); 25 // Must not be in the future 26 if (d > today) return false; 27 28 // OPTIONAL: enforce 18+ 29 // var age = today.getFullYear() - d.getFullYear(); 30 // var m = today.getMonth() - d.getMonth(); 31 // if (m < 0 || (m === 0 && today.getDate() < d.getDate())) age--; 32 // if (age < 18) return false; 33 34 return true; 35 } 36 37 $('form.prizedraws').on('submit', function (e) { 38 e.preventDefault(); 39 40 var $theForm = $(this); 41 var $feedbackContainer = $(this).next('.form-feedback'); 42 43 // Collect dynamic extra fields 44 var extra = {}; 45 $theForm.find('[data-extra-field="1"]').each(function(){ 46 var $f = $(this); 47 var key = ($f.data('key') || '').toString(); 48 var type = ($f.data('type') || '').toString(); 49 var val = $f.val(); 50 51 // Basic type-specific validation (in addition to native attributes) 52 if ($f.prop('required') && (!val || val.trim() === '')) { 53 alert('Please complete the required field: ' + ($f.closest('label').find('p').text() || key)); 54 $f.focus(); 55 extra = null; 56 return false; // break 57 } 58 if (type === 'email' && val && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(val)) { 59 alert('Please enter a valid email address.'); 60 $f.focus(); extra = null; return false; 61 } 62 if (type === 'tel' && val && !/^[0-9()+\-\s]+$/.test(val)) { 63 alert('Please enter a valid telephone number.'); 64 $f.focus(); extra = null; return false; 65 } 66 67 if (key) { extra[key] = val; } 68 }); 69 if (extra === null) { return; } // validation failed 70 71 console.log(extra); 72 73 var demoSubmissions = false; 74 75 if (demoSubmissions === true) { 76 // --- FAKE SUBMISSION FOR DEMO --- 77 $theForm.fadeOut(); 78 $feedbackContainer.fadeIn(); 79 // --- END DEMO --- 80 return; 81 } 82 83 // Gather values 84 var form_data = new FormData(); 85 var nonce = $theForm.data('nonce'); 86 var outletID = $theForm.data('outlet-id'); 87 var postID = $theForm.data('pub-post-id'); 88 var customer_email = $theForm.find('[data-field-name="custemail"]').val(); 89 var customer_name = $theForm.find('[data-field-name="custname"]').val(); 90 91 // NEW fields 92 var customer_phone = $theForm.find('[data-field-name="custphone"]').val(); 93 var customer_dob = $theForm.find('[data-field-name="custdob"]').val(); 94 95 // Append custom fields as JSON 96 form_data.append('extra_json', JSON.stringify(extra)); 97 98 var customerWebsite = $('#cust_website').val(); // Honeypot 99 var marketingOptIn = $('#marketing_optin').prop('checked') ? 1 : 0; 100 101 // Basic required checks already handled by HTML5 'required', 102 // but we add format validation for phone & dob here. 103 if (!isValidPhone(customer_phone)) { 104 alert('Please enter a valid phone number (10â15 digits; you can include spaces or punctuation).'); 105 $theForm.find('#customer_phone').focus(); 106 return; 107 } 108 109 if (!isValidDOB(customer_dob)) { 110 alert('Please enter a valid date of birth (not in the future).'); 111 $theForm.find('#customer_dob').focus(); 112 return; 113 } 114 115 // OPTIONAL: ensure "over 18" checkbox aligns with DOB (uncomment if you want a hard block) 116 // var over18Checked = $('#over_18').prop('checked'); 117 // if (over18Checked) { 118 // var d = new Date(customer_dob); 119 // var today = new Date(); 120 // var age = today.getFullYear() - d.getFullYear(); 121 // var m = today.getMonth() - d.getMonth(); 122 // if (m < 0 || (m === 0 && today.getDate() < d.getDate())) age--;
123 // if (age < 18) { 124 // alert('You must be 18 or over to enter.'); 125 // return; 126 // } 127 // } 128 129 // Abort if honeypot filled 130 if (customerWebsite && customerWebsite.trim() !== '') { 131 // Silently stop bots 132 return; 133 } 134 135 // Build form data 136 form_data.append('nonce', nonce); 137 form_data.append('action', 'prizedrawsform_ajax_handler'); 138 form_data.append('outlet_id', outletID); 139 form_data.append('post_id', postID); 140 form_data.append('customer_email', customer_email); 141 form_data.append('customer_name', customer_name); 142 form_data.append('marketing_optin', marketingOptIn); 143 form_data.append('customerWebsite', customerWebsite); 144 145 // NEW: include phone & dob 146 form_data.append('customer_phone', customer_phone); 147 form_data.append('customer_dob', customer_dob); 148 149 $.ajax({ 150 url: ajax_url, 151 type: 'post', 152 contentType: false, 153 processData: false, 154 data: form_data, 155 success: function (response) { 156 $theForm.hide(); 157 $feedbackContainer.show(); 158 window.scrollTo({ top: 0, left: 0 }); 159 160 if (response && response.data && response.data.code == 3) { 161 $feedbackContainer.append('<h2 style="text-align:left;font-family:sans-serif;">Submitted data for debugging</h2>'); 162 $feedbackContainer.append(createHtmlList(response.data.debug)); 163 console.log(response.data.debug); 164 } 165 }, 166 error: function () { 167 console.log('error'); 168 } 169 }); 170 }); 171 172});
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.