1/** 2 * Form 28 - Election Results - Member/Contact Verification 3 * 4 * Page 1: Submitter verified with name + DOB, then Marae Committee check (must match) 5 * Page 2: Representatives verified with name + DOB (email optional) 6 */ 7(function($) { 8 var verifyTimeout = null; 9 var committeeTimeout = null; 10 var lastVerifiedHash = null; 11 var lastCommitteeHash = null; 12 var isVerifying = false; 13 var isCheckingCommittee = false; 14 var isCheckingElection = false; 15 var committeeVerified = false; // Track if committee check passed 16 var memberVerified = false; // Track if member verification passed 17 var electionVerified = false; // Track if election status check passed 18 19 // Rep verification state - includes verified flag 20 var repState = { 21 rep1: { timeout: null, lastHash: null, isVerifying: false, verified: false }, 22 rep2: { timeout: null, lastHash: null, isVerifying: false, verified: false }, 23 alt: { timeout: null, lastHash: null, isVerifying: false, verified: false } 24 }; 25 26 function getForm28() { return $('#gform_28'); } 27 function sfid() { return $('#input_28_47').val() ? $('#input_28_47').val().trim() : ''; } 28 29 // ========================================================================= 30 // SUBMITTER VERIFICATION (with DOB) + MARAE COMMITTEE CHECK 31 // ========================================================================= 32 33 function injectSubmitterStatusContainer() { 34 var $field53 = $('#field_28_53'); 35 if ($field53.length) { 36 var $content = $field53.find('.gfield_html'); 37 if ($content.length === 0) $content = $field53; 38 $content.attr('id', 'wt-verify-status-28'); 39 } 40 } 41 42 function setSubmitterStatus(html) { 43 var $status = $('#wt-verify-status-28'); 44 if ($status.length) { 45 $status.html(html); 46 } else { 47 var $field53 = $('#field_28_53'); 48 if ($field53.length) $field53.find('.gfield_html').first().html(html); 49 } 50 } 51 52 function readSubmitterInputs() { 53 return { 54 first_name: $('#input_28_40_3').val() ? $('#input_28_40_3').val().trim() : '', 55 middle_name: $('#input_28_40_4').val() ? $('#input_28_40_4').val().trim() : '', 56 last_name: $('#input_28_40_6').val() ? $('#input_28_40_6').val().trim() : '', 57 dob: $('#input_28_43').val() ? $('#input_28_43').val().trim() : '', 58 email: $('#input_28_44').val() ? $('#input_28_44').val().trim() : '', 59 marae: $('#input_28_50').val() ? $('#input_28_50').val().trim() : '', 60 role: getSelectedRole() 61 }; 62 } 63 64 function getSelectedRole() { 65 var role = $('#input_28_51').val() || ''; 66 if (role === 'Other') { 67 role = $('#input_28_52').val() ? $('#input_28_52').val().trim() : ''; 68 } 69 return role; 70 } 71 72 function hashSubmitterInputs(vals) { 73 return vals.first_name + '|' + vals.middle_name + '|' + vals.last_name + '|' + vals.dob; 74 } 75 76 function hashCommitteeInputs(vals) { 77 return vals.first_name + '|' + vals.middle_name + '|' + vals.last_name + '|' + vals.dob + '|' + vals.marae + '|' + vals.role; 78 } 79 80 function validateSubmitter(vals) { 81 if (!vals.first_name || !vals.last_name || !vals.dob) return false; 82 if (!/^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/.test(vals.dob)) return false; 83 return true; 84 } 85 86 function validateCommitteeCheck(vals) { 87 return vals.first_name && vals.last_name && vals.dob && vals.marae && vals.role; 88 } 89 90 function submitterVerifyingUI() { 91 setSubmitterStatus('<div style="padding:12px 15px;background-color:#fff3cd;border:1px solid #ffc107;color:#856404;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;"><strong>Verifying your details...</strong></div>'); 92 } 93 94 function submitterVerifiedUI(data) { 95 $('#input_28_47').val(data.sfid || ''); 96 var message = '<strong>Found in our records.</strong>'; 97 // After member verified, show that we need to check committee 98 var vals = readSubmitterInputs(); 99 if (!vals.marae || !vals.role) { 100 message += '<br><span style="color:#856404;font-size:13px;">Please select your Marae and Role to continue.</span>'; 101 } 102 setSubmitterStatus('<div style="padding:12px 15px;background-color:#e8f5e8;border:1px solid #a5d6a7;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">
102' + message + '</div>'); 103 } 104 105 function committeeVerifyingUI() { 106 var vals = readSubmitterInputs(); 107 var message = '<strong>Found in our records.</strong>'; 108 message += '<br><span style="color:#856404;"><strong>Checking Marae Committee membership...</strong></span>'; 109 setSubmitterStatus('<div style="padding:12px 15px;background-color:#fff3cd;border:1px solid #ffc107;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 110 } 111 112 function committeeVerifiedUI(data) { 113 committeeVerified = true; 114 115 var message = '<strong>Found in our records.</strong>'; 116 var vals = readSubmitterInputs(); 117 message += '<br><span style="color:#1565c0;"><strong>â Verified as ' + vals.role + ' for ' + vals.marae + '</strong></span>'; 118 message += '<br><span style="color:#856404;"><strong>Checking election status...</strong></span>'; 119 setSubmitterStatus('<div style="padding:12px 15px;background-color:#fff3cd;border:1px solid #ffc107;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 120 121 // Now check election status for this marae 122 checkElectionStatus(vals.marae, data); 123 } 124 125 function committeeNotVerifiedUI() { 126 committeeVerified = false; 127 electionVerified = false; 128 disableNextButton(); 129 130 var vals = readSubmitterInputs(); 131 var message = '<strong>Found in our records.</strong>'; 132 message += '<br><span style="color:#c62828;"><strong>â Not found as ' + vals.role + ' for ' + vals.marae + '</strong></span>'; 133 message += '<br><span style="font-size:13px;color:#555;">You must be registered as a committee member to submit election results. Please contact us on 0800 824 684.</span>'; 134 setSubmitterStatus('<div style="padding:12px 15px;background-color:#ffebee;border:1px solid #ef9a9a;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 135 } 136 137 // ========================================================================= 138 // ELECTION STATUS CHECK 139 // ========================================================================= 140 141 function electionVerifiedUI(committeeData, electionData) { 142 electionVerified = true; 143 enableNextButton(); 144 145 // Store election SFID in hidden field (field 63 - needs to be added to form) 146 if (electionData.election_sfid) { 147 $('#input_28_63').val(electionData.election_sfid); 148 } 149 150 var message = '<strong>Found in our records.</strong>'; 151 var vals = readSubmitterInputs(); 152 message += '<br><span style="color:#1565c0;"><strong>â Verified as ' + vals.role + ' for ' + vals.marae + '</strong></span>'; 153 message += '<br><span style="color:#2e7d32;"><strong>â Election open for results submission</strong></span>'; 154 setSubmitterStatus('<div style="padding:12px 15px;background-color:#e8f5e8;border:1px solid #a5d6a7;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 155 } 156 157 function electionNotVerifiedUI(committeeData, errorMessage) { 158 electionVerified = false; 159 disableNextButton(); 160 161 var message = '<strong>Found in our records.</strong>'; 162 var vals = readSubmitterInputs(); 163 message += '<br><span style="color:#1565c0;"><strong>â Verified as ' + vals.role + ' for ' + vals.marae + '</strong></span>'; 164 message += '<br><span style="color:#c62828;"><strong>â ' + (errorMessage || 'No election currently in progress for this marae') + '</strong></span>'; 165 message += '<br><span style="font-size:13px;color:#555;">Results may have already been submitted, or the election hasn\'t started yet. Please contact us on 0800 824 684.</span>'; 166 setSubmitterStatus('<div style="padding:12px 15px;background-color:#ffebee;border:1px solid #ef9a9a;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 167 } 168 169 function checkElectionStatus(marae, committeeData) { 170 if (isCheckingElection) return; 171 if (!marae) { 172 electionNotVerifiedUI(committeeData, 'Marae not specified'); 173 return; 174 } 175 176 isCheckingElection = true; 177 178 $.ajax({ 179 url: window.ajaxurl || '/wp-admin/admin-ajax.php', 180 type: 'POST', 181 dataType: 'json', 182 data: { 183 action: 'check_election_status', 184 marae: marae 185 }, 186 success: function(resp) { 187 isCheckingElection = false;
188 if (resp && resp.success && resp.data && resp.data.status === 'In Progress') { 189 electionVerifiedUI(committeeData, resp.data); 190 } else { 191 var errorMsg = (resp && resp.data && resp.data.message) ? resp.data.message : 'No election in progress'; 192 electionNotVerifiedUI(committeeData, errorMsg); 193 } 194 }, 195 error: function(xhr, status, error) { 196 isCheckingElection = false; 197 electionNotVerifiedUI(committeeData, 'Unable to check election status'); 198 } 199 }); 200 } 201 202 function submitterNotFoundUI() { 203 $('#input_28_47').val(''); 204 $('#input_28_63').val(''); // Clear election SFID 205 committeeVerified = false; 206 electionVerified = false; 207 disableNextButton(); 208 209 var firstName = $('#input_28_40_3').val() ? $('#input_28_40_3').val().trim() : ''; 210 var lastName = $('#input_28_40_6').val() ? $('#input_28_40_6').val().trim() : ''; 211 var name = (firstName + ' ' + lastName).trim() || 'You'; 212 setSubmitterStatus('<div style="padding:12px 15px;background-color:#ffebee;border:1px solid #ef9a9a;color:#c62828;border-radius:4px;font-size:14px;line-height:1.5;"><strong>' + name + '</strong> was not found in our records with the details provided.<br><span style="font-size:13px;">Please check your details or contact us on 0800 824 684.</span></div>'); 213 } 214 215 function submitterWaitingMessage() { 216 committeeVerified = false; 217 electionVerified = false; 218 disableNextButton(); 219 220 var firstName = $('#input_28_40_3').val() ? $('#input_28_40_3').val().trim() : ''; 221 var lastName = $('#input_28_40_6').val() ? $('#input_28_40_6').val().trim() : ''; 222 var dob = $('#input_28_43').val() ? $('#input_28_43').val().trim() : ''; 223 var missingFields = []; 224 if (!firstName) missingFields.push('first name'); 225 if (!lastName) missingFields.push('last name'); 226 if (!dob) missingFields.push('date of birth'); 227 if (missingFields.length > 0 && !sfid()) { 228 setSubmitterStatus('<div style="padding:12px 15px;background-color:#f0f8ff;border:1px solid #b3d4fc;color:#2c3e50;border-radius:4px;font-size:14px;line-height:1.5;"><strong>Verification</strong><br>Please provide your ' + missingFields.join(', ') + ' to verify.</div>'); 229 } 230 } 231 232 // ========================================================================= 233 // NEXT BUTTON CONTROL 234 // ========================================================================= 235 236 function disableNextButton() { 237 var $nextBtn = $('#gform_next_button_28_49, .gform_next_button'); 238 $nextBtn.prop('disabled', true).css('opacity', '0.5').css('cursor', 'not-allowed'); 239 } 240 241 function enableNextButton() { 242 var $nextBtn = $('#gform_next_button_28_49, .gform_next_button'); 243 $nextBtn.prop('disabled', false).css('opacity', '1').css('cursor', 'pointer'); 244 } 245 246 // ========================================================================= 247 // MEMBER VERIFICATION AJAX 248 // ========================================================================= 249 250 function verifySubmitter() { 251 if (isVerifying) return; 252 var vals = readSubmitterInputs(); 253 var hash = hashCommitteeInputs(vals); // Include marae/role in hash 254 255 if (lastVerifiedHash === hash && sfid() && committeeVerified) { 256 // Already verified committee - restore appropriate UI state 257 var message = '<strong>Found in our records.</strong>'; 258 message += '<br><span style="color:#1565c0;"><strong>â Verified as ' + vals.role + ' for ' + vals.marae + '</strong></span>'; 259 260 if (electionVerified) { 261 // Election open - enable button 262 enableNextButton(); 263 message += '<br><span style="color:#2e7d32;"><strong>â Election open for results submission</strong></span>'; 264 setSubmitterStatus('<div style="padding:12px 15px;background-color:#e8f5e8;border:1px solid #a5d6a7;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">
264' + message + '</div>'); 265 } else { 266 // Election not open - keep button disabled 267 disableNextButton(); 268 message += '<br><span style="color:#c62828;"><strong>â No election currently in progress for this marae</strong></span>'; 269 message += '<br><span style="font-size:13px;color:#555;">Results may have already been submitted, or the election hasn\'t started yet. Please contact us on 0800 824 684.</span>'; 270 setSubmitterStatus('<div style="padding:12px 15px;background-color:#ffebee;border:1px solid #ef9a9a;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">' + message + '</div>'); 271 } 272 return; 273 } 274 275 if (!validateSubmitter(vals)) { 276 submitterWaitingMessage(); 277 return; 278 } 279 280 // If marae/role not selected yet, just show waiting message 281 if (!vals.marae || !vals.role) { 282 var message = '<div style="padding:12px 15px;background-color:#f0f8ff;border:1px solid #b3d4fc;color:#2c3e50;border-radius:4px;font-size:14px;line-height:1.5;">'; 283 message += '<strong>Verification</strong><br>Please select your Marae and Role to verify.</div>'; 284 setSubmitterStatus(message); 285 disableNextButton(); 286 return; 287 } 288 289 isVerifying = true; 290 submitterVerifyingUI(); 291 292 // Single call with all details - verify member + committee in one request 293 $.ajax({ 294 url: window.ajaxurl || '/wp-admin/admin-ajax.php', 295 type: 'POST', 296 dataType: 'json', 297 data: { 298 action: 'verify_form_131_contact', // Use same endpoint as Form 131 299 form_id: '28', 300 first_name: vals.first_name, 301 middle_name: vals.middle_name, 302 last_name: vals.last_name, 303 dob: vals.dob, 304 committee_role: vals.role, 305 marae: vals.marae 306 }, 307 success: function(resp) { 308 isVerifying = false; 309 if (resp && resp.success && resp.data && resp.data.contactMatch && resp.data.sfid) { 310 lastVerifiedHash = hash; 311 memberVerified = true; 312 $('#input_28_47').val(resp.data.sfid); 313 314 // Check committee status 315 if (resp.data.isMaraeCommittee === true) { 316 committeeVerified = true; 317 committeeVerifiedUI(resp.data); 318 } else { 319 committeeVerified = false; 320 committeeNotVerifiedUI(); 321 } 322 } else { 323 lastVerifiedHash = null; 324 memberVerified = false; 325 committeeVerified = false; 326 electionVerified = false; 327 submitterNotFoundUI(); 328 } 329 }, 330 error: function(xhr, status, error) { 331 isVerifying = false; 332 lastVerifiedHash = null; 333 memberVerified = false; 334 committeeVerified = false; 335 electionVerified = false; 336 submitterNotFoundUI(); 337 } 338 }); 339 } 340 341 // ========================================================================= 342 // MARAE COMMITTEE CHECK AJAX 343 // ========================================================================= 344 345 function checkMaraeCommittee() { 346 if (isCheckingCommittee) return; 347 if (!memberVerified) return; // Must be verified as member first 348 349 var vals = readSubmitterInputs(); 350 var hash = hashCommitteeInputs(vals); 351 352 if (lastCommitteeHash === hash && committeeVerified) return; 353 354 if (!validateCommitteeCheck(vals)) { 355 // Show message about selecting marae/role 356 var message = '<strong>Found in our records.</strong>'; 357 var missing = []; 358 if (!vals.marae) missing.push('Marae'); 359 if (!vals.role) missing.push('Role'); 360 message += '<br><span style="color:#856404;font-size:13px;">Please select your ' + missing.join(' and ') + ' to continue.</span>'; 361 setSubmitterStatus('<div style="padding:12px 15px;background-color:#e8f5e8;border:1px solid #a5d6a7;color:#2e7d32;border-radius:4px;font-size:14px;line-height:1.5;font-weight:500;">
361' + message + '</div>'); 362 disableNextButton(); 363 return; 364 } 365 366 isCheckingCommittee = true; 367 committeeVerifyingUI(); 368 369 // Convert DOB from dd/mm/yyyy to ISO format for API 370 var dobParts = vals.dob.split('/'); 371 var dobIso = ''; 372 if (dobParts.length === 3) { 373 dobIso = dobParts[2] + '-' + dobParts[1].padStart(2, '0') + '-' + dobParts[0].padStart(2, '0'); 374 } 375 376 $.ajax({ 377 url: window.ajaxurl || '/wp-admin/admin-ajax.php', 378 type: 'POST', 379 dataType: 'json', 380 data: { 381 action: 'verify_waikato_member', 382 form_id: '131', // Use form 131 to trigger committee check 383 first_name: vals.first_name, 384 middle_name: vals.middle_name, 385 last_name: vals.last_name, 386 dob: vals.dob, 387 committee_role: vals.role, 388 marae: vals.marae 389 }, 390 success: function(resp) { 391 isCheckingCommittee = false; 392 lastCommitteeHash = hash; 393 if (resp && resp.success && resp.data && resp.data.isMaraeCommittee) { 394 committeeVerifiedUI(resp.data); 395 } else { 396 committeeNotVerifiedUI(); 397 } 398 }, 399 error: function(xhr, status, error) { 400 isCheckingCommittee = false; 401 lastCommitteeHash = null; 402 committeeNotVerifiedUI(); 403 } 404 }); 405 } 406 407 function scheduleSubmitterVerify() { 408 if (verifyTimeout) clearTimeout(verifyTimeout); 409 verifyTimeout = setTimeout(verifySubmitter, 1500); 410 } 411 412 function scheduleCommitteeCheck() { 413 if (committeeTimeout) clearTimeout(committeeTimeout); 414 committeeTimeout = setTimeout(checkMaraeCommittee, 500); 415 } 416 417 // ========================================================================= 418 // REPRESENTATIVE VERIFICATION (name + DOB required, email optional) 419 // ========================================================================= 420 421 function injectRepStatusContainers() { 422 // Rep 1 - field 54 423 var $field54 = $('#field_28_54'); 424 if ($field54.length) { 425 var $content = $field54.find('.gfield_html'); 426 if ($content.length === 0) $content = $field54; 427 $content.attr('id', 'wt-rep1-status-28'); 428 } 429 // Rep 2 - field 55 430 var $field55 = $('#field_28_55'); 431 if ($field55.length) { 432 var $content = $field55.find('.gfield_html'); 433 if ($content.length === 0) $content = $field55; 434 $content.attr('id', 'wt-rep2-status-28'); 435 } 436 // Alternate - field 56 437 var $field56 = $('#field_28_56'); 438 if ($field56.length) { 439 var $content = $field56.find('.gfield_html'); 440 if ($content.length === 0) $content = $field56; 441 $content.attr('id', 'wt-alt-status-28'); 442 } 443 } 444 445 function setRepStatus(repId, html) { 446 var $status = $('#wt-' + repId + '-status-28'); 447 if ($status.length) { 448 $status.html(html); 449 } 450 } 451 452 // Field mappings for reps - includes SFID hidden fields and DOB 453 var repFields = { 454 rep1: { first: '1_3', middle: '1_4', last: '1_6', dob: '60', email: '4', sfid: '57' }, 455 rep2: { first: '3_3', middle: '3_4', last: '3_6', dob: '61', email: '7', sfid: '58' }, 456 alt: { first: '9_3', middle: '9_4', last: '9_6', dob: '62', email: '10', sfid: '59' } 457 }; 458 459 function readRepInputs(repId) { 460 var f = repFields[repId]; 461 return { 462 first_name: $('#input_28_' + f.first).val() ? $('#input_28_' + f.first).val().trim() : '', 463 middle_name: $('#input_28_' + f.middle).val() ? $('#input_28_' + f.middle).val().trim() : '', 464 last_name: $('#input_28_' + f.last).val() ? $('#input_28_' + f.last).val().trim() : '', 465 dob: $('#input_28_' + f.dob).val() ? $('#input_28_' + f.dob).val().trim() : '', 466 email: $('#input_28_' + f.email).val() ? $('#input_28_' + f.email).val().trim() : '' 467 }; 468 } 469
470 function setRepSfid(repId, sfid) { 471 var f = repFields[repId]; 472 $('#input_28_' + f.sfid).val(sfid || ''); 473 } 474 475 function hashRepInputs(vals) { 476 // Only hash name + DOB - email/phone don't affect verification 477 return vals.first_name + '|' + vals.middle_name + '|' + vals.last_name + '|' + vals.dob; 478 } 479 480 function validateRep(vals) { 481 // Need first name, last name, and valid DOB 482 if (!vals.first_name || !vals.last_name || !vals.dob) return false; 483 // Validate date format (dd/mm/yyyy or d/m/yyyy) 484 if (!/^(0?[1-9]|[12][0-9]|3[01])\/(0?[1-9]|1[0-2])\/\d{4}$/.test(vals.dob)) return false; 485 return true; 486 } 487 488 function repVerifyingUI(repId) { 489 setRepStatus(repId, '<div style="padding:10px 12px;background-color:#fff3cd;border:1px solid #ffc107;color:#856404;border-radius:4px;font-size:13px;line-height:1.4;"><strong>Checking...</strong></div>'); 490 } 491 492 function repVerifiedUI(repId, data) { 493 // Store the SFID in hidden field 494 setRepSfid(repId, data.sfid || ''); 495 repState[repId].verified = true; 496 497 var vals = readRepInputs(repId); 498 var name = (vals.first_name + ' ' + vals.last_name).trim(); 499 var message = '<strong>' + name + '</strong> found in our records.'; 500 setRepStatus(repId, '<div style="padding:10px 12px;background-color:#e8f5e8;border:1px solid #a5d6a7;color:#2e7d32;border-radius:4px;font-size:13px;line-height:1.4;">' + message + '</div>'); 501 502 checkRepVerificationStatus(); 503 } 504 505 function repNotFoundUI(repId) { 506 // Clear the SFID field 507 setRepSfid(repId, ''); 508 repState[repId].verified = false; 509 510 var vals = readRepInputs(repId); 511 var name = (vals.first_name + ' ' + vals.last_name).trim() || 'This person'; 512 setRepStatus(repId, '<div style="padding:10px 12px;background-color:#ffebee;border:1px solid #ef9a9a;color:#c62828;border-radius:4px;font-size:13px;line-height:1.4;"><strong>' + name + '</strong> was not found in our records.<br><span style="font-size:12px;">Please check the name or contact us on 0800 824 684.</span></div>'); 513 514 checkRepVerificationStatus(); 515 } 516 517 // Check if all filled reps are verified and enable/disable submit 518 function checkRepVerificationStatus() { 519 var allVerified = true; 520 521 // Rep 1 is required - must be filled and verified 522 var rep1Vals = readRepInputs('rep1'); 523 if (rep1Vals.first_name && rep1Vals.last_name) { 524 if (!repState.rep1.verified) allVerified = false; 525 } else { 526 // Rep 1 not filled yet - can't submit 527 allVerified = false; 528 } 529 530 // Rep 2 is optional - but if filled, must be verified 531 var rep2Vals = readRepInputs('rep2'); 532 if (rep2Vals.first_name && rep2Vals.last_name) { 533 if (!repState.rep2.verified) allVerified = false; 534 } 535 536 // Alt is optional - but if filled, must be verified 537 var altVals = readRepInputs('alt'); 538 if (altVals.first_name && altVals.last_name) { 539 if (!repState.alt.verified) allVerified = false; 540 } 541 542 if (allVerified) { 543 enableSubmitButton(); 544 } else { 545 disableSubmitButton(); 546 } 547 } 548 549 function disableSubmitButton() { 550 var $submitBtn = $('#gform_submit_button_28, .gform_button[type="submit"]'); 551 $submitBtn.prop('disabled', true).css('opacity', '0.5').css('cursor', 'not-allowed'); 552 } 553 554 function enableSubmitButton() { 555 var $submitBtn = $('#gform_submit_button_28, .gform_button[type="submit"]'); 556 $submitBtn.prop('disabled', false).css('opacity', '1').css('cursor', 'pointer'); 557 } 558 559 function repWaitingMessage(repId) { 560 var vals = readRepInputs(repId); 561 if (!vals.first_name && !vals.last_name && !vals.dob) { 562 setRepStatus(repId, ''); 563 return; 564 } 565 var missingFields = []; 566 if (!vals.first_name) missingFields.push('first name'); 567 if (!vals.last_name) missingFields.push('last name'); 568 if (!vals.dob) missingFields.push('date of birth'); 569 if (missingFields.length > 0) { 570 setRepStatus(repId, '<div style="padding:10px 12px;background-color:#f0f8ff;border:1px solid #b3d4fc;color:#2c3e50;border-radius:4px;font-size:13px;line-height:1.4;">Please enter ' + missingFields.join(', ') + '.</div>'); 571 } 572 } 573 574 function verifyRep(repId) { 575 var state = repState[repId]; 576 if (state.isVerifying) return; 577
578 var vals = readRepInputs(repId); 579 var hash = hashRepInputs(vals); 580 581 // Skip if nothing entered 582 if (!vals.first_name && !vals.last_name) { 583 setRepStatus(repId, ''); 584 return; 585 } 586 587 // If hash unchanged and already verified, restore verified state 588 if (state.lastHash === hash && state.verified) { 589 enableSubmitButton(); 590 checkRepVerificationStatus(); 591 return; 592 } 593 if (state.lastHash === hash) return; 594 595 if (!validateRep(vals)) { 596 repWaitingMessage(repId); 597 return; 598 } 599 600 state.isVerifying = true; 601 repVerifyingUI(repId); 602 603 $.ajax({ 604 url: window.ajaxurl || '/wp-admin/admin-ajax.php', 605 type: 'POST', 606 dataType: 'json', 607 data: { 608 action: 'verify_rep_member', 609 form_id: '28', 610 first_name: vals.first_name, 611 middle_name: vals.middle_name, 612 last_name: vals.last_name, 613 dob: vals.dob, 614 email: vals.email 615 }, 616 success: function(resp) { 617 state.isVerifying = false; 618 state.lastHash = hash; 619 if (resp && resp.success && resp.data && resp.data.memberMatch && resp.data.sfid) { 620 repVerifiedUI(repId, resp.data); 621 } else { 622 repNotFoundUI(repId); 623 } 624 }, 625 error: function() { 626 state.isVerifying = false; 627 state.lastHash = hash; 628 repNotFoundUI(repId); 629 } 630 }); 631 } 632 633 function scheduleRepVerify(repId) { 634 var state = repState[repId]; 635 if (state.timeout) clearTimeout(state.timeout); 636 637 // Check if hash actually changed before resetting verified status 638 var vals = readRepInputs(repId); 639 var hash = hashRepInputs(vals); 640 if (state.lastHash !== hash) { 641 // Hash changed - need to re-verify 642 state.verified = false; 643 disableSubmitButton(); 644 } 645 646 state.timeout = setTimeout(function() { verifyRep(repId); }, 1500); 647 } 648 649 // ========================================================================= 650 // INITIALIZATION & BINDINGS 651 // ========================================================================= 652 653 function bindForm28Verification() { 654 var $form = getForm28(); 655 if (!$form.length) return; 656 657 // Submitter fields (page 1) - trigger verification 658 $form.on('input change blur', '#input_28_40_3, #input_28_40_4, #input_28_40_6, #input_28_43', function() { 659 scheduleSubmitterVerify(); 660 }); 661 662 // Marae and Role fields - also trigger verification (single call does both) 663 $form.on('change', '#input_28_50, #input_28_51', function() { 664 lastVerifiedHash = null; // Force re-verify with new marae/role 665 scheduleSubmitterVerify(); 666 }); 667 668 // Other role text field 669 $form.on('input blur', '#input_28_52', function() { 670 lastVerifiedHash = null; // Force re-verify 671 scheduleSubmitterVerify(); 672 }); 673 674 // Rep 1 fields (name, DOB only - email/phone don't affect verification) 675 $form.on('input change blur', '#input_28_1_3, #input_28_1_4, #input_28_1_6, #input_28_60', function() { 676 scheduleRepVerify('rep1'); 677 }); 678 679 // Rep 2 fields (name, DOB only) 680 $form.on('input change blur', '#input_28_3_3, #input_28_3_4, #input_28_3_6, #input_28_61', function() { 681 scheduleRepVerify('rep2'); 682 }); 683 684 // Alternate fields (name, DOB only) 685 $form.on('input change blur', '#input_28_9_3, #input_28_9_4, #input_28_9_6, #input_28_62', function() { 686 scheduleRepVerify('alt'); 687 }); 688 } 689 690 function checkExistingSubmitterVerification() { 691 var vals = readSubmitterInputs(); 692 if (vals.first_name && vals.last_name && vals.dob) { 693 // Trigger single verification call (member + committee in one) 694 scheduleSubmitterVerify(); 695 } else if (vals.first_name || vals.last_name || vals.dob) { 696 submitterWaitingMessage(); 697 } else { 698 disableNextButton(); 699 } 700 } 701 702 // ========================================================================= 703 // COPY PAGE 1 VALUES TO "CERTIFIED BY" SECTION ON PAGE 2 704 // ========================================================================= 705 706 function copySubmitterToCertifiedBy() { 707 // Read values from page 1 fields
708 var firstName = $('#input_28_40_3').val() || ''; 709 var middleName = $('#input_28_40_4').val() || ''; 710 var lastName = $('#input_28_40_6').val() || ''; 711 var email = $('#input_28_44').val() || ''; 712 713 // Get role - field 51 dropdown, or field 52 if "Other" 714 var role = $('#input_28_51').val() || ''; 715 if (role === 'Other') { 716 role = $('#input_28_52').val() || 'Other'; 717 } 718 719 // Populate "Certified by" fields (field 18 name, field 21 email, field 19 role) 720 $('#input_28_18_3').val(firstName); 721 $('#input_28_18_4').val(middleName); 722 $('#input_28_18_6').val(lastName); 723 $('#input_28_21').val(email); 724 $('#input_28_19').val(role); 725 726 // Copy membersfid (field 47) to sfid_submittedby (field 22) 727 var memberSfid = $('#input_28_47').val() || ''; 728 $('#input_28_22').val(memberSfid); 729 } 730 731 function initAll() { 732 if (!$('#gform_28').length) return; 733 injectSubmitterStatusContainer(); 734 injectRepStatusContainers(); 735 bindForm28Verification(); 736 737 // Disable Next button by default until committee verified 738 disableNextButton(); 739 740 checkExistingSubmitterVerification(); 741 } 742 743 $(document).ready(function() { 744 initAll(); 745 }); 746 747 $(document).on('gform_post_render', function(event, formId) { 748 if (parseInt(formId, 10) === 28) { 749 setTimeout(function() { 750 injectSubmitterStatusContainer(); 751 injectRepStatusContainers(); 752 bindForm28Verification(); 753 disableNextButton(); 754 checkExistingSubmitterVerification(); 755 }, 500); 756 } 757 }); 758 759 $(document).on('gform_page_loaded', function(event, formId, currentPage) { 760 if (parseInt(formId, 10) === 28) { 761 setTimeout(function() { 762 if (currentPage == 1) { 763 injectSubmitterStatusContainer(); 764 disableNextButton(); 765 checkExistingSubmitterVerification(); 766 } else if (currentPage == 2) { 767 injectRepStatusContainers(); 768 769 // Disable submit until reps verified 770 disableSubmitButton(); 771 772 // Copy submitter details to "Certified by" section 773 copySubmitterToCertifiedBy(); 774 775 // Check existing rep data and verify 776 ['rep1', 'rep2', 'alt'].forEach(function(repId) { 777 var vals = readRepInputs(repId); 778 if (vals.first_name && vals.last_name) { 779 scheduleRepVerify(repId); 780 } 781 }); 782 783 // Initial check of verification status 784 checkRepVerificationStatus(); 785 } 786 }, 500); 787 } 788 }); 789 790})(jQuery);
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.