JSFiddle - React, Tailwind, and code Playground
by jquery4u
HTML
<script src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.11.1/jquery.validate.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css">
<script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.js"></script>
<form id="signup" class="step3 form-horizontal" action="" method="POST">
<h2>Tell Your Friends</h2>
<p>Tell your friends about the Highlands photography competition to receive a bonus 10 photos to enter* into the competition. To skip this step simply leave the fields blank and click next.</p>
<div class="control-group">
<div class="control-group-inner">
<label class="control-label" for="friend1-name">Friend's name</label>
<div class="controls">
<input type="text" name="friend1-name" placeholder="Friend's name... " />
</div>
</div>
<div class="control-group-inner">
<label class="control-label" for="friend1-email">Email Address</label>
<div class="controls">
<input type="text" name="friend1-email" placeholder="Email Address... " />
</div>
</div>
</div>
<div class="control-group">
<div class="control-group-inner">
<label class="control-label" for="friend2-name">Friend's name</label>
<div class="controls">
<input type="text" name="friend2-name" placeholder="Friend's name... " />
</div>
</div>
<div class="control-group-inner">
<label class="control-label" for="friend2-email">Email Address</label>
...
CSS
.control-group {
width: 100%;
}
.control-group-inner {
width: 50%;
float: left;
display: inline-block;
}
/* step 3 */
.step3 .control-group {
width: 100%;
}
.step3 .control-group-inner {
width: 50%;
float: left;
display: inline-block;
}
.step3 .control-group .control-label {
width: 100px !important;
text-align: left !important;
font-size: 0.9em;
}
.step3 .control-group .controls {
margin-left: 100px;
padding-right: 10px;
}
.step3 input[type="text"] {
width: 190px;
}
.step3 h2 {
margin-bottom: 5px;
line-height: 1em;
}
.step3 .bonus-txt {
font-size: 0.8em;
}
.step3 {
margin-bottom: 60px;
}
.step3 .next {
float: right;
margin-right: 50px;
}
/* validation errors */
label.error, .form-error {
color: #F00;
font-size: 0.9em;
margin: 0;
}
input.error {
border-color: red;
}
JavaScript
//custom validation: each friend entered must have an email and a name
$.validator.addMethod("fieldPresent", function (value, element, options)
{
//we need the validation error to appear on the correct element
var targetEl = $('input[name="'+options.data+'"]'),
targetEmpty = (targetEl.val() == ''),
elEmpty = (value == ''),
bothEmpty = elEmpty && targetEmpty;
//trigger error class on target input
if (!bothEmpty && targetEmpty)
{
//error msg doesn't exist yet so wait...
setTimeout(function()
{
if (targetEl.closest('.control-group-inner').find('label.fieldPresentError').length == 0)
{
targetEl.addClass('error');
if (!elEmpty) $(element).closest('.control-group-inner').find('label.fieldPresentError').remove();
targetEl.closest('.control-group-inner').find('label.fieldPresentError').remove();
targetEl.after("<label class='error fieldPresentError'>Friend's name and email required.</label>");
}
}, 500);
}
return (bothEmpty || !elEmpty);
},
"Friend's name and email required."
);
//for quick demo..
var form3 = $('form.step3');
form3.validate({
onkeyup: false,
rules: {
"friend1-name": { "fieldPresent": { data: "friend1-email" } },
"friend1-email": { "fieldPresent": { data: "friend1-name" }, email: true },
"friend2-name": { "fieldPresent": { data: "friend2-email" } },
"friend2-email": { "fieldPresent": { data: "friend2-name" }, email: true },
"friend3-name": { "fieldPresent": { data: "friend3-email" } },
"friend3-email": { "fieldPresent": { data: "friend3-name" }, email: true },
"friend4-name": { "fieldPresent": { data: "friend4-email" } },
...