<div id="css-table">
  <div id="col-1">
   <ul>
    <li><a href="#col-1-tab-1">Example 9<br>&nbsp;
    </a></li>
   </ul>
   <div id="col-1-tab-1">
    <article>
     <h2>Form Validation</h2>
     <p>
     This example illustrates a complete form validation with <b>apg-exp</b>.
     In the function <code>$(document).ready</code>, all of the SABNF patterns are defined and the
     respective <code>ApgExp</code> objects are constructed.
     All message strings are defined there as well
      </p>
     <p>
     The function <code>validate()</code> is called when the "submit" button is clicked.
     Each input value is validated with the corresponding <code>ApgExp.test()</code> function.
     The password requires four separate tests to validate the character type and number requirements.
      </p>
      <ul>
      <li>User names must be 3-32 characters, contain only letters, numbers, hyphens and periods and begin with a letter.</li>
      <li>The email address is the same as <a class="link" href="https://codepen.io/SitePoint/pen/gMLgZQ">Example 1</a>.</li>
      <li>Passwords must be 8-16 characters and contain only letters and numbers. At least one each of upper case letter,
      lower case letter and number is required.</li>
      </ul>
     <form onSubmit="return validate()">
<pre>
           <span id="error-name" class="form"></span>
user name: <input id="form-name" type="text"><br>
           <span id="error-email" class="form"></span>
    email: <input id="form-email" type="text"><br>
           <span id="error-password" class="form"></span>
 password: <input id="form-password" type="password"><br>
           <span id="error-confirm" class="form"></span>
  confirm: <input id="form-confirm" type="password"><br>
</pre>
      <input type="submit">
     </form>
    </article>
   </div>
  </div>
  
  <div id="col-2">
   <ul>
    <li><a href="#col-2-tab-1">Validation Output</a></li>
   </ul>
   <div id="col-2-tab-1">
    <article>
     <div id="tab-1-here"></div>
    </article>
   </div>

  </div>
 </div>
/* Pen-specific styles */
* {
	box-sizing: border-box;
}

body {
	color: #000;
	font-size: .8rem;
	line-height: 150%;
}

h1 {
	font-size: 1.75rem;
	margin: 0 0 0.75rem 0;
	font-family: 'Open Sans', sans-serif;
	font-weight: 700;
}

h2 {
	font-family: 'Open Sans', sans-serif;
	font-weight: 700;
}

article {
	font-family: 'Open Sans', sans-serif;
	font-weight: 400;
}

b {
	font-family: 'Open Sans', sans-serif;
	font-weight: 700;
}

i {
	font-family: 'Open Sans', sans-serif;
	font-style: italic;
}

textarea {
	width: 100%;
}

button {
	cursor: pointer;
	cursor: hand;
}

p.title {
	margin: 0px 0px 3px 0px;
}

a.link {
	color: #4284B0;
	text-decoration: none;
}

a.link:visited {
	color: #9c4be7;
  text-decoration: none;
}

/* Pattern styles */
#css-table {
	display: table;
	width: 100%;
}

#css-table > div {
	border: 1px solid #4284B0;
  margin-bottom: 1em;
}

textarea#grammar {
	height: 10rem;
	font-family: monospace;
}

textarea#input {
	height: 5rem;
	font-family: monospace;
}

.example {
	display: table;
	width: 100%;
}

.discuss {
	display: table-cell;
	width: 40%;
	/*width: 25rem;
  float: left;
	*/
}

button {
	width: 5rem;
}

span.form{
	color: red;
}

pre > input{
	width: 20rem;
}
var strings = {};
var exp = {};
var validate = function(){
  var input, result;
  var success = true;
  
  // validate name
  input  = $("#form-name").val();
  result = exp.name.test(input);
  if(result){
    $("#error-name").html("");
  }else{
    $("#error-name").html(strings.nameError);
    success = false;
  }
  
  // validate email
  input  = $("#form-email").val();
  result = exp.email.test(input);
  if(result){
    $("#error-email").html("");
  }else{
    $("#error-email").html(strings.emailError);
    success = false;
  }
  
  // validate password
  var pwd       = $("#form-password").val();
  var hasUpper  = exp.upper.test(pwd);
  var hasLower  = exp.lower.test(pwd);
  var hasNumber = exp.number.test(pwd);
  var hasCount  = exp.count.test(pwd);
  if((hasUpper && hasLower && hasNumber && hasCount)){
    $("#error-password").html("");
  }else{
    $("#error-password").html(strings.passwordError);
    success = false;
  }
  
  // confirm password
  var confirm = $("#form-confirm").val();
  if(confirm === pwd){
    $("#error-confirm").html("");
  }else{
    $("#error-confirm").html(strings.confirmError);
    success = false;
  }
  
  if(success){
    $("#tab-1-here").html(strings.success);
  }else{
    $("#tab-1-here").html(strings.failure);
  }
  return false;
}
$(document).ready(function() {
  // email pattern
  strings.email = "";
  strings.email += 'email-address   = %^ local "@" domain %$\n';
  strings.email += 'local           = local-word *("." local-word)\n';
  strings.email += 'domain          = 1*(sub-domain ".") top-domain\n';
  strings.email += 'local-word      = 1*local-char\n';
  strings.email += 'sub-domain      = 1*sub-domain-char\n';
  strings.email += 'top-domain      = 2*6top-domain-char\n';
  strings.email += 'local-char      = alpha / num / special\n';
  strings.email += 'sub-domain-char = alpha / num / "-"\n';
  strings.email += 'top-domain-char = alpha\n';
  strings.email += 'alpha           = %d65-90 / %d97-122\n';
  strings.email += 'num             = %d48-57\n';
  strings.email += 'special         = %d33      / %d35 / %d36-39\n';
  strings.email += '                  / %d42-43 / %d45 / %d47\n';
  strings.email += '                  / %d61    / %d63 / %d94-96\n';
  strings.email += '                  / %d123-126\n';
  
  // name pattern
  strings.name = "";
  strings.name += "name    = %^ alpha 2*31(alpha / special) %$\n";
  strings.name += "alpha   = %d65-90 / %d97-122\n";
  strings.name += "special = %d48-57 / %d45-46\n";
  
  // password patterns
  strings.upper  = "upper = %d65-90\n";
  strings.lower  = "lower = %d97-122\n";
  strings.number = "number = %d48-57\n";
  strings.count  = "count = %^ 8*16(%d65-90 / %d97-122 / %d48-57) %$\n";
  
  // error messages
  strings.emailError    = "Please enter a valid email address.";
  strings.nameError     = "Please enter a valid user name.";
  strings.passwordError = "Please enter a valid password.";
  strings.confirmError  = "Password and confirmation do not match.";
  
  // form submission messages
  strings.success = "<h2>Thank you!</h2>You have successfully signed up.";
  strings.failure = "<h2>We're sorry.</h2>The data you have entered is incorrect.<br>Please try again.";
  
  // ApgExp objects
  exp.email  = new ApgExp(strings.email);
  exp.name   = new ApgExp(strings.name);
  exp.upper  = new ApgExp(strings.upper);
  exp.lower  = new ApgExp(strings.lower);
  exp.number = new ApgExp(strings.number);
  exp.count  = new ApgExp(strings.count);

  // set up tabs
  $("#col-1").tabs();
  $("#col-2").tabs();
});
Run Pen

External CSS

  1. https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/start/jquery-ui.css
  2. https://cdn.rawgit.com/ldthomas/apg-js2-exp/89c6681798ba9e47583b685c87b244406b18a26d/apgexp.css
  3. https://fonts.googleapis.com/css?family=Open+Sans:400,400italic,700,700italic

External JavaScript

  1. https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js
  2. https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js
  3. https://cdn.rawgit.com/ldthomas/apg-js2-exp/c0fc3adac954a6f6ad6f265fd2f8f06f68001e10/apgexp-min.js