1// Contact form and reCAPTCHA processing 2(function ($) { 3 var captchaLoaded = false; // Flags when Google reCAPTCHA script has been added to the page 4 5 // Define constraints for form error checking here; please see: https://validatejs.org/ 6 var constraints = { 7 // Each is the "name" field of the input! 8 name: { 9 presence: { 10 message: "^Please enter your name", 11 }, 12 }, 13 email: { 14 presence: { 15 message: "^Please enter your email address", 16 }, 17 email: { 18 message: "^Invalid email address", 19 }, 20 }, 21 phone: { 22 presence: { 23 message: "^Please enter your phone number", 24 }, 25 format: { 26 pattern: "^[0-9/-]+$", 27 message: "^Phone number can only contain numbers and dashes", 28 }, 29 length: { 30 minimum: 7, 31 tooShort: "^Please enter at least %{count} characters", 32 }, 33 }, 34 }; 35 36 $(function () { 37 // Load reCAPTCHA script when certain form field is focused 38 $(".contact-form input, .contact-form textarea").on("focus", function () { 39 // Check that the script hasn't already loaded 40 if (captchaLoaded) { 41 return; 42 } 43 44 console.log("reCAPTCHA script loading."); 45 46 var head = document.getElementsByTagName("head")[0]; 47 var script = document.createElement("script"); 48 script.type = "text/javascript"; 49 script.src = "https://www.google.com/recaptcha/api.js"; 50 head.appendChild(script); 51 captchaLoaded = true; // Set flag to only load once 52 }); 53 54 $(".contact-form input").on("focusout", function (event) { 55 // "Live validation" - Validates form input when it loses focus 56 errors = validate($(this).closest("form"), constraints); 57 58 // Look for matching errors specific to this input 59 applyInputErrors($(this), errors); 60 }); 61 62 // Remove input error when it is focused 63 $("input").on("focusin", function (event) { 64 resetInputErrors($(this)); 65 }); 66 }); 67 68 $(".contact-form").submit(function (e) { 69 // This BLOCKS submission of the form. The reCAPTCHA callback function submits 70 e.preventDefault(); 71 console.log("Contact form submitted."); 72 73 // On form submit, run validate.js on the form using defined constraints 74 errors = validate($(this), constraints); 75 76 // If errors are found, prevent form submission and provide feedback 77 if (errors) { 78 $(this) 79 .find("input") 80 .each(function () { 81 // Loop through inputs on the form, finding any error corresponding to this field's "name" 82 applyInputErrors($(this), errors); 83 }); 84 } else { 85 var captchaID = getCaptchaID($(this).find(".g-recaptcha").attr("id")); 86 87 grecaptcha.reset(captchaID); 88 grecaptcha.execute(captchaID); 89 } 90 }); 91 92 // In case of multiple forms, returns unique ID of a specific reCAPTCHA so correct one is submitted 93 function getCaptchaID(containerID) { 94 var returnedID = -1; 95 96 $(".g-recaptcha").each(function (index) { 97 if (this.id == containerID) { 98 returnedID = index; 99 return; 100 } 101 }); 102 103 return returnedID; 104 } 105 106 // Input validation: Searches any error corresponding to this field's "name" 107 function applyInputErrors(inputToCheck, errorsList) { 108 var matchingError = errorsList[$(inputToCheck).attr("name")]; 109 110 if (matchingError) { 111 // If there IS an error on this input, add styling and error text 112 resetInputErrors($(inputToCheck)); // Remove existing errors 113 $(inputToCheck).addClass("has-error"); 114 $(inputToCheck) 115 .parent() 116 .append("<p class='error-text'>" + matchingError + "</p>"); 117 } 118 } 119 120 // Input validation: Reset errors shown on input 121 // Called when input is focused and when a new error is being applied 122 function resetInputErrors(inputToReset) { 123 $(inputToReset).removeClass("has-error"); 124 $(inputToReset).siblings("p.error-text").remove(); 125 } 126})(jQuery); 127 128// Handle invisible reCAPTCHA on submit 129function submitContactStandard(token) { 130 console.log("Invisible reCAPTCHA submitted: #contact-formStandard"); 131 document.getElementById("contact-formStandard").submit(); 132} 133 134// Handle additional contact form on same page 135function submitContactFooter(token) { 136 document.getElementById("contact-formFooter").submit(); 137}
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.