<div class="ads-content">
			<h1>Accessible form including JavaScript validation and inline error messages</h1>
			<p>This accessible form example uses HTML, CSS, and Vanilla JavaScript coding best-practices and meets all WCAG 2.1 requirements. This form was tested using keyboard-only, browser zoom 400%, text resize 200%, Windows high contrast theme, Chrome, Firefox, Edge, Safari, mobile devices and emulators, and NVDA, JAWS, and VoiceOver screen readers.</p>
			<p>Inline error messages are shown on "submit" button activation only, however, they are removed after the user fixes the error and tabs off the field using the JavaScript on "blur" event.</p>
			<p>After passing all form validation and submitting the form, a success message is shown.</p>
			
			<!-- Form heading -->
			<h2 id="formHeader">Information request</h2>			
		
			<!-- START: Form tag -->
			<form novalidate id="myForm" aria-labelledby="formHeader">
				
				<!-- Start: form instructions -->
				<p>We will respond to your inquiry within 2 business days.</p>
				<p>Fields marked with a red asterisk <span class="ads-asterisk" aria-hidden="true">*</span> are required.</p>				
				<!-- /END: form instructions -->
				<br>
				
				<div class="ads-flexLayout">
					<!-- START: First Name input field -->
					<div>
						<label id="firstNameLabel" for="firstName">First name <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" name="firstName" id="firstName" autocomplete="given-name" aria-required="true" aria-describedby="firstNameError">
						</div>
						<div class="ads-error-message" data-error-for="firstName" id="firstNameError"></div>
					</div>

					<!-- START: Middle Initial input field -->
					<div>
						<label id="middleInitialLabel" for="middleInitial">Middle initial</label>
						<div class="ads-inputWrapper">
							<input type="text" name="middleInitial" id="middleInitial">
						</div>
					</div>

					<!-- START: Last Name input field -->
					<div>
						<label id="lastNameLabel" for="lastName">Last name <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" name="lastName" id="lastName" autocomplete="family-name" aria-required="true" aria-describedby="lastNameError">
						</div>
						<div class="ads-error-message" data-error-for="lastName" id="lastNameError"></div>
					</div>
				</div>

				<!-- START: US Mailing Address Group -->
				<fieldset>
					<legend>US mailing address</legend>
					<div class="ads-flexLayout ads-formField">
						<div>
							<label for="street_address1">Street address 1 <span class="ads-asterisk" aria-hidden="true">*</span></label>
							<div class="ads-inputWrapper">
								<input type="text" id="street_address1" name="street_address1" autocomplete="address-line1" aria-describedby="street_address1Error" aria-required="true">
							</div>
							<div class="ads-error-message" data-error-for="street_address1" id="street_address1Error"></div>
						</div>

						<div>
						  <label for="street_address2">Street address 2</label>
						  <div class="ads-inputWrapper">
							<input type="text" id="street_address2" name="street_address2" autocomplete="address-line2">
						  </div>	  
						</div>

						<div>
						  <label for="city">City <span class="ads-asterisk" aria-hidden="true">*</span></label>
						  <div class="ads-inputWrapper">
							<input type="text" id="city" name="city" autocomplete="address-level2" aria-describedby="cityError" aria-required="true">
						  </div>
						  <div class="ads-error-message" data-error-for="city" id="cityError"></div>
						</div>
					</div>

				<div class="ads-flexLayout">
					<div>
						<label for="state">State <span class="ads-asterisk" aria-hidden="true">*</span></label>		
						<!--- United States states -->
						<div class="ads-inputWrapper">
							<select id="state" name="state" autocomplete="address-level1" aria-describedby="stateError" aria-required="true">
								<option value="" disabled selected> -- Select a state -- </option>
								<option value="AL">Alabama</option>
								<option value="AK">Alaska</option>
								<option value="AS">American Samoa</option>
								<option value="AZ">Arizona</option>
								<option value="AR">Arkansas</option>
								<option value="UM-81">Baker Island</option>
								<option value="CA">California</option>
								<option value="CO">Colorado</option>
								<option value="CT">Connecticut</option>
								<option value="DE">Delaware</option>
								<option value="DC">District of Columbia</option>
								<option value="FL">Florida</option>
								<option value="GA">Georgia</option>
								<option value="GU">Guam</option>
								<option value="HI">Hawaii</option>
								<option value="UM-84">Howland Island</option>
								<option value="ID">Idaho</option>
								<option value="IL">Illinois</option>
								<option value="IN">Indiana</option>
								<option value="IA">Iowa</option>
								<option value="UM-86">Jarvis Island</option>
								<option value="UM-67">Johnston Atoll</option>
								<option value="KS">Kansas</option>
								<option value="KY">Kentucky</option>
								<option value="UM-89">Kingman Reef</option>
								<option value="LA">Louisiana</option>
								<option value="ME">Maine</option>
								<option value="MD">Maryland</option>
								<option value="MA">Massachusetts</option>
								<option value="MI">Michigan</option>
								<option value="UM-71">Midway Atoll</option>
								<option value="MN">Minnesota</option>
								<option value="MS">Mississippi</option>
								<option value="MO">Missouri</option>
								<option value="MT">Montana</option>
								<option value="UM-76">Navassa Island</option>
								<option value="NE">Nebraska</option>
								<option value="NV">Nevada</option>
								<option value="NH">New Hampshire</option>
								<option value="NJ">New Jersey</option>
								<option value="NM">New Mexico</option>
								<option value="NY">New York</option>
								<option value="NC">North Carolina</option>
								<option value="ND">North Dakota</option>
								<option value="MP">Northern Mariana Islands</option>
								<option value="OH">Ohio</option>
								<option value="OK">Oklahoma</option>
								<option value="OR">Oregon</option>
								<option value="UM-95">Palmyra Atoll</option>
								<option value="PA">Pennsylvania</option>
								<option value="PR">Puerto Rico</option>
								<option value="RI">Rhode Island</option>
								<option value="SC">South Carolina</option>
								<option value="SD">South Dakota</option>
								<option value="TN">Tennessee</option>
								<option value="TX">Texas</option>
								<option value="UM">United States Minor Outlying Islands</option>
								<option value="VI">United States Virgin Islands</option>
								<option value="UT">Utah</option>
								<option value="VT">Vermont</option>
								<option value="VA">Virginia</option>
								<option value="UM-79">Wake Island</option>
								<option value="WA">Washington</option>
								<option value="WV">West Virginia</option>
								<option value="WI">Wisconsin</option>
								<option value="WY">Wyoming</option>
							</select>		
						</div>
						<div class="ads-error-message" data-error-for="state" id="stateError"></div>
					</div>

					<div>
						<label for="zip_code">5-digit US zip code <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" id="zip_code" name="zip_code" autocomplete="postal-code" maxlength="5" aria-describedby="zip_codeError" aria-required="true">
						</div>
						<div class="ads-error-message" data-error-for="zip_code" id="zip_codeError"></div>
					</div>
				</div>
			</fieldset>	
			<!-- /END: US Mailing Address Group -->


			<!-- START: Date of Birth Group -->
			<fieldset class="ads-birthDate ads-formField">

				<legend>Date of birth</legend>
				<div class="ads-flexLayout">
					<!-- START: Birth Month select element -->
					<div>
						<label id="birthMonthLabel" for="birthMonth">Birth month <span class="ads-asterisk" aria-hidden="true">*</span></label>	
						<div class="ads-inputWrapper">
							<select name="birthMonth" id="birthMonth" aria-required="true" aria-describedby="birthMonthError">
								<option value="0" disabled selected>-- Select a month --</option>
								<option value="1">January</option>
								<option value="2">February</option>
								<option value="3">March</option>
								<option value="4">April</option>
								<option value="5">May</option>
								<option value="6">June</option>
								<option value="7">July</option>
								<option value="8">August</option>
								<option value="9">September</option>
								<option value="10">October</option>
								<option value="11">November</option>
								<option value="12">December</option>
							</select>
							</div>
						<div class="ads-error-message" data-error-for="birthMonth" id="birthMonthError"></div>
					</div>
					<!-- /END: Birth Month select element -->

					<!-- START: Birth Day input field -->
					<div>
						<label id="birthDayLabel" for="birthDay">2-digit birth day <span class="ads-hintText">(example: 05)</span> <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" name="birthDay" id="birthDay" autocomplete="bday-day" aria-describedby="birthDayError" aria-required="true" maxlength="2">
						</div>
						<div class="ads-error-message" data-error-for="birthDay" id="birthDayError"></div>
					</div>
					<!-- /END: Birth Day input field -->

					<!-- START: Birth Year input field -->
					<div>
						<label id="birthYearLabel" for="birthYear">4-digit birth year <span class="ads-hintText">(example: 1958)</span> <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" name="birthYear" id="birthYear" autocomplete="bday-year" aria-describedby="birthYearError" aria-required="true" maxlength="4">
						</div>
						<div class="ads-error-message" data-error-for="birthYear" id="birthYearError"></div>
					</div>
					<!-- /END: Birth Year input field -->

				</div>

			</fieldset>	
			<!-- /END: Date of Birth Group -->


			<!-- START: Contact Info group including email and mobile input fields -->
			<fieldset>
				<legend>Contact info</legend>
				<div class="ads-flexLayout">
					<div class="ads-formField">
						<label id="emailLabel" for="email">Email <span class="ads-asterisk" aria-hidden="true">*</span></label>
						<div class="ads-inputWrapper">
							<input type="text" name="email" id="email" autocomplete="email" aria-required="true" aria-describedby="emailError">
						</div>
						<div class="ads-error-message" data-error-for="email" id="emailError"></div>
					</div>
					<div class="ads-formField">
						<label id="phoneLabel" for="phone">Mobile <span class="ads-hintText">(example: 617-555-1212)</span> <span class="ads-asterisk" aria-hidden="true">*</span></label>

						<div class="ads-inputWrapper">
							<input type="tel" name="phone" id="phone" aria-required="true" autocomplete="tel" aria-describedby="phoneError">
						</div>
						<div class="ads-error-message" data-error-for="phone" id="phoneError"></div>
					</div>
				</div>
			</fieldset>
			<!-- /END: Contact Info group including email and mobile input fields -->


			<div class="ads-flexLayout">
				<!-- START: Call Back Time checkbox group -->
				<fieldset>
					<legend>What time would you like a call back?</legend>
					<ul class="ads-checkboxUl">
						<li><label for="morning"><input type="checkbox" id="morning" name="morning"> Morning</label></li>
						<li><label for="afternoon"><input type="checkbox" id="afternoon" name="afternoon"> Afternoon</label></li>
						<li><label for="evening"><input type="checkbox" id="evening" name="evening"> Evening</label></li>
					</ul>
				</fieldset>	
				<!-- /END: Call Back Time checkbox button group -->

				<!-- START: Security Code radio button group -->
				<fieldset aria-required="true" id="securityCode" aria-describedby="securityCodeError">
					<legend>How do you want to receive your security code? <span class="ads-asterisk" aria-hidden="true">*</span></legend>
					<ul class="ads-radioUl">
						<li><label for="securityCode_email"><input type="radio" id="securityCode_email" name="securityCode" value="email"> Email</label></li>
						<li><label for="securityCode_text"><input type="radio" id="securityCode_text" name="securityCode" value="text"> Text</label></li>
					</ul>
					<div class="ads-error-message" data-error-for="securityCode" id="securityCodeError"></div>	
				</fieldset>	
				<!-- /END: Security Code radio button group -->
			</div>


			<div class="ads-flexLayout">
			<!-- START: Message textarea with dynamic character counter -->
				<div class="ads-formField ads-textAreaTopMargin">
					<div class="ads-input-row">
					  <label class="ads-input-label" id="ads-input-label-123" for="textarea-123">Message <span class="ads-asterisk" aria-hidden="true">*</span> <span class="ads-visually-hidden">100 maximum character count</span></label>
					  <div class="ads-input-character-count" id="ads-input-character-count-123"><span id="textarea-count-123" >100</span> of <span id="textarea-max-123">100</span> characters left</div>							
					  <span class="ads-visually-hidden" id="textarea-count-alert-123"></span>					
					</div>

					<div class="ads-input-content-container">
					  <textarea name="comments" id="textarea-123" aria-describedby="messageError" maxlength="100" aria-required="true" cols="2"></textarea>
					</div>
					<div class="ads-error-message" data-error-for="textarea-123" id="messageError"></div>
				</div>					  
			  <!-- /END: Message textarea with dynamic character counter -->
			</div>


			<!-- Form submit button -->
			<button id="submitForm" type="submit" class="ads-btn ads-btn-primary">Submit</button>

		</form>
		<!-- /END: Form tag -->	


		<!-- START: Success message after form submit -->
		<div style="display:none;" id="successMessageBox" class="ads-success-message">
			<span id="successMessageText" class="ads-success-message-text">Form submitted successfully</span>
			<button id="successMessageCloseBtn" aria-describedby="successMessageText" class="ads-success-message-close" onClick="closeMessage()">Close <span class="ads-visually-hidden">message</span></button>
		</div>
		<!-- /END: Success message after form submit -->



		<h2>Additional Resources</h2>
		<ul class="ads-list">
		  <li><a href="https://www.w3.org/WAI/WCAG21/Understanding/info-and-relationships.html" target="_blank">WCAG 2.1 Success Criterion 1.3.1 Info and Relationships (Level A) (opens in new tab)</a></li>
		  <li><a href="https://www.w3.org/WAI/WCAG21/Understanding/labels-or-instructions.html" target="_blank">WCAG 2.1 Success Criterion 3.3.2: Labels or Instructions (Level A) (opens in new tab)</a></li>
		  <li><a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-required" target="_blank"><code>aria-required</code> attribute (opens in new tab)</a></li>
		 <li><a href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-invalid" target="_blank"><code>aria-invalid</code> attribute (opens in new tab)</a></li>
		  <li><a href="https://www.w3.org/WAI/tutorials/forms/instructions/#using-aria-describedby" target="_blank">W3C Form Instructions examples using <code>aria-describedby</code> (opens in new tab)</a></li>
			 <li><a href="https://www.w3schools.com/tags/att_input_autocomplete.asp" target="_blank">W3C HTML input <code>autocomplete</code> Attribute (opens in new tab)</a></li>
			<li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete" target="_blank">MMDN HTML attribute: <code>autocomplete</code> (opens in new tab)</a></li>
		  <li><a href="https://codepen.io/EOTSS-ACCESS/pen/zxYxJoz" target="_blank">Accessible Success Message CodePen Example using <code>aria-describedby</code> (opens in new tab)</a></li>
		</ul>
	</div>
/* CSS styles only needed for CodePen Prototpye */
/************************************************/
a,abbr,address,article,aside,audio,b,blockquote,body,canvas,caption,cite,code,dd,del,details,dfn,div,dl,dt,em,fieldset,figcaption,figure,footer,form,header,hgroup,hr,html,i,iframe,img,ins,kbd,label,legend,li,mark,menu,nav,object,ol,pre,q,samp,section,small,span,strong,sub,summary,sup,table,tbody,td,tfoot,th,thead,time,tr,ul,var,video{
	margin:0;
	padding:0;
	border:0;
	line-height:1.5;
	text-shadow:none;
}


/* CSS style to make all elements inherit same width when setting min-width  */
*, *::before, *::after {
  box-sizing: border-box;
}

body {font-family: "Arial", sans-serif; font-size:1rem; line-height:1.5;}
body img {max-width:100%; height:auto;}
.ads-content {
	padding:1REM;
	margin-bottom:1REM;
}
h1 {line-height:1.4;margin:.5rem 0;padding:0;}
h2 {font-weight:normal;margin:1.5rem 0 0;padding:0;}


.ads-container {
	padding:1REM;
	margin-bottom:1REM;
	display: flex;
	gap:1REM;
	align-items: center;
}

ul.ads-list {
	margin:.5rem 0 .5rem 1.5rem;
}

li {padding-bottom:.5rem;}


*:focus {
	/* inner indicator */
	outline: 2px #F9F9F9 solid;
	outline-offset: 0;
	/* outer indicator */
	box-shadow: 0 0 0 4px #0088ff;
}

input[type="radio"]:focus {
	/* outer indicator */
	outline: 2px #0088ff solid;
	outline-offset: 2px;
	box-shadow: none;
}

/* CSS used for visually hidden text */
.ads-visually-hidden {
  clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}

a {text-decoration:underline;color: #14558F;}
a:hover {text-decoration:none;}


.ads-btn, .ads-btn-group, .ads-btn-primary {
	padding: .75rem 1.5rem;
	font-size: 1.125rem;
	line-height: 1.2;
	vertical-align: middle;
	border-radius: 0.5rem;
	letter-spacing: 0;
	font-weight: 400;
	text-transform: none;
	margin: 1rem .125rem;
}
.ads-btn-primary {
	color: #fff;
	background-color: #14558f;
	border: 1px solid #14558f;
}

.ads-btn-primary:hover {
	background-color:#4377A5;
	border-color:#4377A5;
}

.ads-btn-primary:active {
	background-color:#104472;
	border-color:#104472;
}

.ads-code {
	font-family: Monospace, "Courier New", "Lucida Bright", "DejaVu Serif", Georgia, "serif";
}


/* default color of Google Chrome of the disabled option in the select tag didn't meet the contrast requirement of 4.5:1 */
select option:disabled {
  background-color: #666; /* Light grey background for disabled options */
	color: #fff; /* Darker text color for disabled options */
}
.ads-inputWrapper {margin-bottom:.25rem;}
.ads-formField {}
.ads-textAreaTopMargin {margin-top:1rem;}
.ads-asterisk {color:#cd0d0d;}
.ads-error-message {margin:0;color:#cd0d0d;display: flex;align-items: flex-start; gap:.25rem;line-height:1.5;}
.ads-error-message span {flex:1;}
ul.ads-checkboxUl, ul.ads-radioUl {list-style: none;padding:0;margin:0;}
ul.ads-radioUl {display: flex;gap:1rem;align-items:center;}
ul.ads-radioUl li {margin:0;padding:0;}
form {padding:1rem 0;}
form p {padding:0; margin:0 0 .25rem;}
fieldset {border:none;margin:0;padding:0;}
.ads-flexLayout {display: flex; gap:2rem; align-items: flex-start;}
.ads-flexLayout div:last-child {margin-bottom:.5rem;}
p.ads-hintText {color:#666;padding:0;margin:0 0 .25rem;}
.ads-hintText {color:#666;}
legend {font-size:1.125rem;line-height:1.5;font-weight:bold;margin:0;padding:.75rem 0 .25rem;}
label {font-size:1rem;}
select, input[type="text"], input[type="email"], input[type="file"], input[type="date"], input[type="search"], input[type="month"], input[type="url"], input[type="tel"], textarea {background:#fff;border:2px solid #949494;padding:.5rem;font-size:1rem;line-height:1.4;min-width:298px;border-radius:.5rem;margin:.125rem;}
textarea {border:2px solid #949494;padding:.5rem;line-height:1.5;width:550px;min-height:100px;border-radius:.5rem;}
select {padding:.6rem 0;}

fieldset.ads-birthDate input {max-width:60px;} /* don't make it smaller otherwise text will be clipped when the user sets font-size in the browser to xtra large */

/* red border styles for input fields when they have an error */
/* select.ads-errorBorder, input.ads-errorBorder {border-color: #cd0d0d;} */

/* textarea styles */
.ads-input-instructions,
.ads-input-character-count {   
  font-size:0.875rem
}


.ads-input-row {
	display: flex;
	width: 100%;
	justify-content: space-between;
	align-items: flex-end;
}
.ads-input-content-container {
	display: flex;
	width: 100%;
	margin-bottom:.5REM 
}
textarea.ads-input-content {			
	margin: 0.125rem;
	width: 100%;
}

/* CSS for SVG image that works with contrast themes */
svg {fill:currentColor;}


/* success message styles */
.ads-success-message {margin:1em 0;padding:1em;display: flex;background:#EBF3EE;border:#9CC2AB 1px solid;border-radius:1em;justify-content: space-between;align-items: center;}
.ads-success-message-text {}
.ads-success-message-close {color:#333;border:2px solid #388557;background:#EBF3EE;border-radius:.25em;padding:.5em .75em;}
button.ads-success-message-close:focus {outline-width: 2px;outline-offset: 4px;}

@media screen and (max-width: 1160px) {
	form {padding:1rem .25rem;}
	.ads-content {padding:.25rem;}
	.ads-flexLayout {flex-direction: column;gap:.5rem;margin-bottom:.25rem;}
	.ads-flexLayout div:last-child {margin-bottom:.5rem;}
  	select, input[type="text"], input[type="email"], input[type="file"], input[type="date"], input[type="search"], input[type="month"], input[type="url"], input[type="tel"], textarea {min-width:296px;width:auto;}
}
/* Accessible Inline Form Validation JavaScript */
 
const errorIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" aria-label="Error:" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z"/></svg>';
const numberRegex = /^\d+$/;	
const firstNameInput = document.getElementById('firstName');
const lastNameInput = document.getElementById('lastName');
const streetAddress1Input = document.getElementById('street_address1');
const cityInput = document.getElementById('city');
const stateSelect = document.getElementById('state');
const zipCodeInput = document.getElementById('zip_code');
const birthMonthSelect = document.getElementById('birthMonth');
const birthDayInput = document.getElementById('birthDay');
const birthYearInput = document.getElementById('birthYear');
const emailInput = document.getElementById('email');
const phoneInput = document.getElementById('phone');
const securityCodeRadio = document.querySelectorAll('input[name="securityCode"]');
const messageInput = document.getElementById("textarea-123"); 
const messageError = document.getElementById("messageError");

/* security code radio button isChecked variable */
let isChecked = false;

/* text area counter */
let myMaxLength = 100, // textarea maxlength, set it to whatever you want, update the maxlength HTML attribute on the textarea field with this value
	myAlertTheshold = 20, // the threshold where the ARIA alert will start firing, don't set it too low
	maximum = document.getElementById("textarea-max-123"), // the maximum character count SPAN
    characterCounter = document.getElementById("textarea-count-123"), //the current character count
    messageAlert = document.getElementById("textarea-count-alert-123"); //count alert container

/* initialise the character count area */
maximum.setAttribute('maxlength', myMaxLength);
characterCounter.innerHTML=myMaxLength;  //.text() doesn't work with screen reader

/* respond to each keydown by incrementing or decrementing the current character count */

messageInput.addEventListener('keyup', function(e) {
  let characterCount = this.value.length,
      charactersRemaining = myMaxLength - characterCount;
	
      characterCounter.innerHTML=charactersRemaining;

  //hide the error message if at least one character is shown
  if (characterCount > 0) {
      messageError.innerHTML = "";
  }

  /* once characters entered reaches the predefined threshold, create a new aria-alert 
	element so the screen reader receives the alert */

  /* creates the new element for each character up to the final one, so an alert happens for each keypress */	
  if (charactersRemaining <= myAlertTheshold) {
    messageAlert.setAttribute("role", "alert");
    messageAlert.innerHTML = charactersRemaining + ' of ' + myMaxLength + ' characters left';
  } else {
    messageAlert.removeAttribute("role");
    messageAlert.innerHTML = "";
  }
});



function validateEmailSimple(email) {
  const atIndex = email.indexOf('@');
  const dotIndex = email.indexOf('.', atIndex); // Find the first dot after the @ symbol
  //console.log(email + "at index: " + atIndex + ", dot Index: " + dotIndex);
  if (atIndex === -1 && dotIndex === -1) { // both @ and dot missing
	  //console.log("both dot and @ are missing");
	  document.querySelector('[data-error-for="email"]').innerHTML = errorIcon + ' <span>Email is missing the "@" symbol and a period (dot).</span>';
	  return false;
  } else if (atIndex === -1) { // Check if @ is present
	//console.log("@ is missing");
  	document.querySelector('[data-error-for="email"]').innerHTML = errorIcon + ' <span>Email is missing the "@" symbol.</span>';
	return false;
  } else if (atIndex === 0) { // Check if @ is not the first character
	//console.log("@ is first character");
	document.querySelector('[data-error-for="email"]').innerHTML = errorIcon + ' <span>Email can\'t start with the \"@\" symbol.</span>';	
	return false;
  } else if (dotIndex === -1 || dotIndex < atIndex) { //no dot after @ symbol
	//console.log("both dot is missing");
	document.querySelector('[data-error-for="email"]').innerHTML = errorIcon + ' <span>Email is missing a period (dot).</span>';  
	return false;
  } else {
	//console.log("email is valid: " + email);
	document.querySelector('[data-error-for="email"]').innerHTML = "";
	emailInput.setAttribute("aria-invalid","false");			
	emailInput.classList.remove("ads-errorBorder");
	return true;
  }
}

function validateSecurityRadioGroup(event) {	
	for (let i = 0; i < securityCodeRadio.length; i++) {
		if (securityCodeRadio[i].checked) {
			isChecked = true;
			break;
		}
	}

	if (isChecked) {
		//console.log("hide radio error message");
		document.querySelector('[data-error-for="securityCode"]').innerHTML = "";		
	} else {
		if(event == "click") {
			//console.log("show radio error message");
			document.querySelector('[data-error-for="securityCode"]').innerHTML = errorIcon + ' <span>Please choose a security code sending format.</span>';
		}
	}
		
}
	
  document.getElementById('myForm').addEventListener('submit', function(event) {
        event.preventDefault(); // Prevent default form submission
	  
	  	let firstErrorField = null; // To store the first field with an error
       
        // Clear previous error messages
        document.querySelectorAll(".ads-error-message").forEach(errorSpan => {
            errorSpan.innerHTML = "";
        });

        

        // Validate First Name
        if (firstNameInput.value.trim() === '') {
            document.querySelector('[data-error-for="firstName"]').innerHTML = errorIcon + ' <span>Please enter a first name.</span>';
			firstNameInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = firstNameInput;
            }
        } else {
			document.querySelector('[data-error-for="firstName"]').innerHTML = "";
			firstNameInput.classList.remove("ads-errorBorder");
		}
	  
	  	// Validate Last Name
        if (lastNameInput.value.trim() === '') {
            document.querySelector('[data-error-for="lastName"]').innerHTML = errorIcon + ' <span>Please enter a last name.</span>';
			lastNameInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = lastNameInput;
            }
        } else {
			document.querySelector('[data-error-for="lastName"]').innerHTML = "";
			lastNameInput.classList.remove("ads-errorBorder");
		}
	  
		// Validate mailing address
	  	if (streetAddress1Input.value.trim() === '') {
            document.querySelector('[data-error-for="street_address1"]').innerHTML = errorIcon + ' <span>Please enter a street address.</span>';
			streetAddress1Input.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = streetAddress1Input;
            }
        } else {
			document.querySelector('[data-error-for="street_address1"]').innerHTML = "";
			streetAddress1Input.classList.remove("ads-errorBorder");
		}
	  
	   if (cityInput.value.trim() === '') {
            document.querySelector('[data-error-for="city"]').innerHTML = errorIcon + ' <span>Please enter a city.</span>';
			cityInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = cityInput;
            }
        } else {
			document.querySelector('[data-error-for="city"]').innerHTML = "";
			cityInput.classList.remove("ads-errorBorder");
		}
	  
	    if (stateSelect.value == "") {
            document.querySelector('[data-error-for="state"]').innerHTML = errorIcon + ' <span>Please select a state.</span>';
			stateSelect.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = stateSelect;
            }
        } else {
			document.querySelector('[data-error-for="state"]').innerHTML = "";
			stateSelect.classList.remove("ads-errorBorder");
		}
	  
	  	if (zipCodeInput.value.trim() === '') {
            document.querySelector('[data-error-for="zip_code"]').innerHTML = errorIcon + ' <span>Please enter a zip code.</span>';
			zipCodeInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = zipCodeInput;
            }
		} else if (zipCodeInput.value.length < 5 || isNaN(zipCodeInput.value)) {
            document.querySelector('[data-error-for="zip_code"]').innerHTML = errorIcon + ' <span>Please enter a 5-digit zip code.</span>';
			zipCodeInput.classList.add("ads-errorBorder");
			zipCodeInput.setAttribute("aria-invalid","true");
            if (!firstErrorField) {
                firstErrorField = zipCodeInput;
            }       
        } else {
			document.querySelector('[data-error-for="zip_code"]').innerHTML = "";
			zipCodeInput.setAttribute("aria-invalid","false");
			zipCodeInput.classList.remove("ads-errorBorder");
		}
	  	
	    // Validate Birth Month - select element
        if (birthMonthSelect.value < 1) {
            document.querySelector('[data-error-for="birthMonth"]').innerHTML = errorIcon + ' <span>Please select a birth month.</span>';
			birthMonthSelect.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = birthMonthSelect;
            }
        } else {
			document.querySelector('[data-error-for="birthMonth"]').innerHTML = "";
			birthMonthSelect.classList.remove("ads-errorBorder");
		}
	  
	    // Validate Birth Day
        if (birthDayInput.value.trim() === '') {
            document.querySelector('[data-error-for="birthDay"]').innerHTML = errorIcon + ' <span>Please enter a birth day.</span>';
			birthDayInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = birthDayInput;
            }
		} else if (birthDayInput.value.length < 2 || isNaN(birthDayInput.value)) {
            document.querySelector('[data-error-for="birthDay"]').innerHTML = errorIcon + ' <span>Please enter a 2-digit birth day.</span>';
			birthDayInput.classList.add("ads-errorBorder");
			birthDayInput.setAttribute("aria-invalid","true");
            if (!firstErrorField) {
                firstErrorField = birthDayInput;
            }
       
        } else {
			document.querySelector('[data-error-for="birthDay"]').innerHTML = "";
			birthDayInput.setAttribute("aria-invalid","false");
			birthDayInput.classList.remove("ads-errorBorder");
		}
	  
	  
	    // Validate Birth Year
        if (birthYearInput.value.trim() === '') {
            document.querySelector('[data-error-for="birthYear"]').innerHTML = errorIcon + ' <span>Please enter a birth year.</span>';
			birthYearInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = birthYearInput;
            }
		} else if (birthYearInput.value.length < 4 || isNaN(birthYearInput.value)) {
            document.querySelector('[data-error-for="birthYear"]').innerHTML = errorIcon + ' <span>Please enter a 4-digit birth year.</span>';
			birthYearInput.setAttribute("aria-invalid","true");
			birthYearInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = birthYearInput;
            }
        } else {
			birthYearInput.setAttribute("aria-invalid","false");
			document.querySelector('[data-error-for="birthYear"]').innerHTML = "";
			birthYearInput.classList.remove("ads-errorBorder");
		}

        // Validate Email
	    if (emailInput.value.trim() === '') {
            document.querySelector('[data-error-for="email"]').innerHTML = errorIcon + ' <span>Please enter an email.</span>';
			emailInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = emailInput;
            }
        } else if (!validateEmailSimple(emailInput.value)) { //check errors and return descriptive error message
			//console.log("email has an error");
			emailInput.setAttribute("aria-invalid","true");
			emailInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = emailInput;
            }        
        } 
	 
	  
	    if (phoneInput.value.trim() === '') {
            document.querySelector('[data-error-for="phone"]').innerHTML = errorIcon + ' <span>Please enter a mobile number.</span>';
			phoneInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = phoneInput;
            }
			// phone number has 10 digits and 2 dashes - maximum of 12 characters 
		} else if (phoneInput.value.trim().length < 12 || phoneInput.value.trim().length > 12) { 
			
			//trim the phone input value and remove any empty characters
			phoneInput.value = phoneInput.value.trim();
            document.querySelector('[data-error-for="phone"]').innerHTML = errorIcon + ' <span>Please enter a 10-digit mobile number.</span>';
			phoneInput.setAttribute("aria-invalid","true");
			phoneInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = phoneInput;
            }
        } else {
			phoneInput.setAttribute("aria-invalid","false");
			document.querySelector('[data-error-for="phone"]').innerHTML = "";
			phoneInput.classList.remove("ads-errorBorder");
		}
	  
	    // validate security radio group
	    validateSecurityRadioGroup("click");
	     
	  
	    /* textarea input field */
	    if(messageInput.value == "") {
			document.querySelector('[data-error-for="textarea-123"]').innerHTML = errorIcon + ' <span>Please enter a message.</span>';
			messageInput.classList.add("ads-errorBorder");
            if (!firstErrorField) {
                firstErrorField = messageInput;
            }
		  } else {
			document.querySelector('[data-error-for="textarea-123"]').innerHTML = "";
			messageInput.classList.remove("ads-errorBorder");
		  }

        // Focus on the first field with an error
        if (firstErrorField) {
            firstErrorField.focus();
        } else {
            // If no errors, you can submit the form programmatically or perform other actions
            // alert('Form submitted successfully!');
			// this.submit(); // Uncomment to submit the form if valid
			
			//clear form fields
			document.getElementById("myForm").reset(); 
			//show success message after successful submit
			document.getElementById("successMessageBox").style.display="flex";
			document.getElementById("successMessageCloseBtn").focus();
        }
    });	
	
	/* clear error messages after user fixes them and tabs off using the on "blur" event */
	
	// First Name
	firstNameInput.addEventListener('blur', function(event) {
        if (firstNameInput.value.trim() !== '') {            
			document.querySelector('[data-error-for="firstName"]').innerHTML = "";
			firstNameInput.classList.remove("ads-errorBorder");
		}
	}); 
	
	// Last Name
	lastNameInput.addEventListener('blur', function(event) {
        if (lastNameInput.value.trim() !== '') {            
			document.querySelector('[data-error-for="lastName"]').innerHTML = "";
			lastNameInput.classList.remove("ads-errorBorder");
		}
	});
	
	// Mailing address
	streetAddress1Input.addEventListener('blur', function(event) {
        if (streetAddress1Input.value.trim() !== '') {            
			document.querySelector('[data-error-for="street_address1"]').innerHTML = "";
			streetAddress1Input.classList.remove("ads-errorBorder");
		}
	});
	
	
	// City
	cityInput.addEventListener('blur', function(event) {
        if (cityInput.value.trim() !== '') {            
			document.querySelector('[data-error-for="city"]').innerHTML = "";
			cityInput.classList.remove("ads-errorBorder");
		}
	});
	
	// State select
	stateSelect.addEventListener('blur', function(event) {
        if (stateSelect.value !== "") {            
			document.querySelector('[data-error-for="state"]').innerHTML = "";
			stateSelect.classList.remove("ads-errorBorder");
		}
	});
	
	// Zip code
	zipCodeInput.addEventListener('blur', function(event) {
         if ((zipCodeInput.value.trim() !== '') && (numberRegex.test(zipCodeInput.value)) && (zipCodeInput.value.length == 5)) {           
			document.querySelector('[data-error-for="zip_code"]').innerHTML = "";
			zipCodeInput.setAttribute("aria-invalid","false");
			zipCodeInput.classList.remove("ads-errorBorder");
		}								  
	});
	
	// Birth month select
	birthMonthSelect.addEventListener('blur', function(event) {
        if (birthMonthSelect.value > 0) {            
			document.querySelector('[data-error-for="birthMonth"]').innerHTML = "";
			birthMonthSelect.classList.remove("ads-errorBorder");
		}
	});
	
	
	// Birth Day
	birthDayInput.addEventListener('blur', function(event) {
         if ((birthDayInput.value.trim() !== '') && (numberRegex.test(birthDayInput.value)) && (birthDayInput.value.length == 2)) {           
			document.querySelector('[data-error-for="birthDay"]').innerHTML = "";
			birthDayInput.setAttribute("aria-invalid","false");
			birthDayInput.classList.remove("ads-errorBorder");
		}								  
	});
	
	// Birth Year
	birthYearInput.addEventListener('blur', function(event) {
         if ((birthYearInput.value.trim() !== '') && (numberRegex.test(birthYearInput.value)) && (birthYearInput.value.length == 4)) {           
			document.querySelector('[data-error-for="birthYear"]').innerHTML = "";
			birthYearInput.setAttribute("aria-invalid","false");
			birthYearInput.classList.remove("ads-errorBorder");
		}								  
	});
	
	// Email
	emailInput.addEventListener('blur', function(event) {
        if ((emailInput.value.trim() !== '') && (/^\S+@\S+\.\S+$/.test(emailInput.value))) {            
			document.querySelector('[data-error-for="email"]').innerHTML = "";
			emailInput.setAttribute("aria-invalid","false");			
			emailInput.classList.remove("ads-errorBorder");
		}
	});
	
	// Mobile Phone -- format phone number with dashes on blur and remove errors if it validates
	phoneInput.addEventListener('blur', function(e) {
	  let phoneNumber = this.value.replace(/\D/g, ''); // Remove non-numeric characters
	  phoneNumber.trim(); // remove any blank spaces
	  if (phoneNumber.length > 9) {
		this.value = phoneNumber.slice(0, 3) + '-' + phoneNumber.slice(3, 6) + '-' + phoneNumber.slice(6); /* Add dashes after 3rd and 6th digits, don't trim the end of the number if there are more than 10 digits in the originally entered phone number. If a user makes a mistake they can fix it during the regular form validation on submit button press. */
	  } 
		
	  if (phoneInput.value.trim().length == 12) {            
			phoneInput.setAttribute("aria-invalid","false");
			document.querySelector('[data-error-for="phone"]').innerHTML = "";
			phoneInput.classList.remove("ads-errorBorder");
		}
	});

		
	// Attach blur event listener to each radio button
    securityCodeRadio.forEach(radio => {
        radio.addEventListener('blur', function(e) {
			validateSecurityRadioGroup("blur");
		});
    });

    // Optional: Also validate on change for immediate feedback
    securityCodeRadio.forEach(radio => {
		radio.addEventListener('change', function(e) {
			validateSecurityRadioGroup("change");
		});
        
    });
	
	// Message textarea - this is not needed since we hide the error message once the user types at least one character. If you don't use a charcter counter, then you can use this function to hide the error message
/*
	messageInput.addEventListener('blur', function(event) {
        if (messageInput.value !== "") {            
			document.querySelector('[data-error-for="textarea-123"]').innerHTML = "";
			messageInput.classList.remove("ads-errorBorder");
		}
	}); */

// Close confirmation message function when close button is activated
function closeMessage() {
 	document.getElementById("successMessageBox").style.display="none";
	document.getElementById("submitForm").focus();
}
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.