upgraded validator plug-in

This commit is contained in:
pratik 2020-01-06 17:13:26 +05:30
parent f0106934c9
commit 4fb515d0b7
13 changed files with 1275 additions and 6947 deletions

View file

@ -50,7 +50,7 @@
"jquery.inputmask": "^3.3.1", "jquery.inputmask": "^3.3.1",
"jquery-knob": "^1.2.13", "jquery-knob": "^1.2.13",
"cropper": "^2.3.0", "cropper": "^2.3.0",
"validator": "https://github.com/yairEO/validator.git#^1.0.6", "validator": "https://github.com/yairEO/validator.git#^3.3.5",
"jQuery-Smart-Wizard": "^3.3.1", "jQuery-Smart-Wizard": "^3.3.1",
"dropzone": "^4.3.0", "dropzone": "^4.3.0",
"pnotify": "^3.0.0", "pnotify": "^3.0.0",

5948
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,10 +33,10 @@
"devDependencies": { "devDependencies": {
"browser-sync": "^2.26.7", "browser-sync": "^2.26.7",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-autoprefixer": "^3.1.0", "gulp-autoprefixer": "^7.0.1",
"gulp-concat": "^2.6.0", "gulp-concat": "^2.6.1",
"gulp-rename": "^1.4.0", "gulp-rename": "^2.0.0",
"gulp-ruby-sass": "^2.0.6", "gulp-ruby-sass": "^4.0.0",
"gulp-uglify": "^1.5.3" "gulp-uglify": "^3.0.2"
} }
} }

View file

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<!-- Meta, title, CSS, favicons, etc. --> <!-- Meta, title, CSS, favicons, etc. -->
@ -142,7 +143,8 @@
</li> </li>
</ul> </ul>
</li> </li>
<li><a href="javascript:void(0)"><i class="fa fa-laptop"></i> Landing Page <span class="label label-success pull-right">Coming Soon</span></a></li> <li><a href="javascript:void(0)"><i class="fa fa-laptop"></i> Landing Page <span
class="label label-success pull-right">Coming Soon</span></a></li>
</ul> </ul>
</div> </div>
@ -177,7 +179,8 @@
<nav class="nav navbar-nav"> <nav class="nav navbar-nav">
<ul class=" navbar-right"> <ul class=" navbar-right">
<li class="nav-item dropdown open" style="padding-left: 15px;"> <li class="nav-item dropdown open" style="padding-left: 15px;">
<a href="javascript:;" class="user-profile dropdown-toggle" aria-haspopup="true" id="navbarDropdown" data-toggle="dropdown" aria-expanded="false"> <a href="javascript:;" class="user-profile dropdown-toggle" aria-haspopup="true" id="navbarDropdown"
data-toggle="dropdown" aria-expanded="false">
<img src="images/img.jpg" alt="">John Doe <img src="images/img.jpg" alt="">John Doe
</a> </a>
<div class="dropdown-menu dropdown-usermenu pull-right" aria-labelledby="navbarDropdown"> <div class="dropdown-menu dropdown-usermenu pull-right" aria-labelledby="navbarDropdown">
@ -192,7 +195,8 @@
</li> </li>
<li role="presentation" class="nav-item dropdown open"> <li role="presentation" class="nav-item dropdown open">
<a href="javascript:;" class="dropdown-toggle info-number" id="navbarDropdown1" data-toggle="dropdown" aria-expanded="false"> <a href="javascript:;" class="dropdown-toggle info-number" id="navbarDropdown1" data-toggle="dropdown"
aria-expanded="false">
<i class="fa fa-envelope-o"></i> <i class="fa fa-envelope-o"></i>
<span class="badge bg-green">6</span> <span class="badge bg-green">6</span>
</a> </a>
@ -291,7 +295,8 @@
<li><a class="collapse-link"><i class="fa fa-chevron-up"></i></a> <li><a class="collapse-link"><i class="fa fa-chevron-up"></i></a>
</li> </li>
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-wrench"></i></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i
class="fa fa-wrench"></i></a>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton"> <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#">Settings 1</a> <a class="dropdown-item" href="#">Settings 1</a>
<a class="dropdown-item" href="#">Settings 2</a> <a class="dropdown-item" href="#">Settings 2</a>
@ -303,86 +308,91 @@
<div class="clearfix"></div> <div class="clearfix"></div>
</div> </div>
<div class="x_content"> <div class="x_content">
<form class="" action="" method="post" novalidate>
<form class="form-horizontal form-label-left" novalidate> <p>For alternative validation library <code>parsleyJS</code> check out in the <a
href="form.html">form page</a>
<p>For alternative validation library <code>parsleyJS</code> check out in the <a href="form.html">form page</a>
</p> </p>
<span class="section">Personal Info</span> <span class="section">Personal Info</span>
<div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Name<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="name">Name <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input id="name" class="form-control" data-validate-length-range="6" data-validate-words="2" name="name" placeholder="both name(s) e.g Jon Doe" required="required" type="text"> <input class="form-control" data-validate-length-range="6" data-validate-words="2" name="name"
placeholder="ex. John f. Kennedy" required="required" />
</div> </div>
</div> </div>
<div class="item form-group"> <div class="field item form-group">
<label class="col-form-label col-md-3 col-sm-3 label-align" for="email">Email <span class="required">*</span> <label class="col-form-label col-md-3 col-sm-3 label-align">Occupation<span
</label> class="required">*</span></label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input type="email" id="email" name="email" required="required" class="form-control"> <input class="form-control" class='optional' name="occupation" data-validate-length-range="5,15"
type="text" /></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">email<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="email">Confirm Email <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input type="email" id="email2" name="confirm_email" data-validate-linked="email" required="required" class="form-control"> <input class="form-control" name="email" class='email' required="required" type="email" /></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Confirm email address<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="number">Number <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input type="number" id="number" name="number" required="required" data-validate-minmax="10,100" class="form-control"> <input class="form-control" type="email" class='email' name="confirm_email"
data-validate-linked='email' required='required' /></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Number <span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="website">Website URL <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input type="url" id="website" name="website label-align" required="required" placeholder="www.website.com" class="form-control"> <input class="form-control" type="number" class='number' name="number"
data-validate-minmax="10,100" required='required'></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Date<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="occupation">Occupation <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input id="occupation" type="text" name="occupation" data-validate-length-range="5,20" class="optional form-control"> <input class="form-control" class='date' type="date" name="date" required='required'></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Time<span
<label for="password" class="col-form-label col-md-3 label-align">Password</label> class="required">*</span></label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input id="password" type="password" name="password" data-validate-length="6,8" class="form-control" required="required"> <input class="form-control" class='time' type="time" name="time" required='required'></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Password<span
<label for="password2" class="col-form-label col-md-3 col-sm-3 label-align ">Repeat Password</label> class="required">*</span></label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input id="password2" type="password" name="password2" data-validate-linked="password" class="form-control" required="required"> <input class="form-control" type="password" name="password" data-validate-length="6,8"
required='required' /></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Repeat password<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="telephone">Telephone <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<input type="tel" id="telephone" name="phone" required="required" data-validate-length-range="8,20" class="form-control"> <input class="form-control" type="password" name="password2" data-validate-linked='password'
required='required' /></div>
</div> </div>
</div> <div class="field item form-group">
<div class="item form-group"> <label class="col-form-label col-md-3 col-sm-3 label-align">Telephone<span
<label class="col-form-label col-md-3 col-sm-3 label-align" for="textarea">Textarea <span class="required">*</span> class="required">*</span></label>
</label>
<div class="col-md-6 col-sm-6"> <div class="col-md-6 col-sm-6">
<textarea id="textarea" required="required" name="textarea" class="form-control"></textarea> <input class="form-control" type="tel" class='tel' name="phone" required='required'
data-validate-length-range="8,20" /></div>
</div> </div>
<div class="field item form-group">
<label class="col-form-label col-md-3 col-sm-3 label-align">message<span
class="required">*</span></label>
<div class="col-md-6 col-sm-6">
<textarea required="required" name='message'></textarea></div>
</div> </div>
<div class="ln_solid"></div> <div class="ln_solid">
<div class="form-group"> <div class="form-group">
<div class="col-md-6 offset-md-3"> <div class="col-md-6 offset-md-3">
<button type="submit" class="btn btn-primary">Cancel</button> <button type='submit' class="btn btn-primary">Submit</button>
<button id="send" type="submit" class="btn btn-success">Submit</button> <button type='reset' class="btn btn-success">Reset</button>
</div>
</div> </div>
</div> </div>
</form> </form>
@ -405,6 +415,34 @@
</div> </div>
</div> </div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="../vendors/validator/multifield.js"></script>
<script src="../vendors/validator/validator.js"></script>
<script>
// initialize a validator instance from the "FormValidator" constructor.
// A "<form>" element is optionally passed as an argument, but is not a must
var validator = new FormValidator({ "events": ['blur', 'input', 'change'] }, document.forms[0]);
// on form "submit" event
document.forms[0].onsubmit = function (e) {
var submit = true,
validatorResult = validator.checkAll(this);
console.log(validatorResult);
return !!validatorResult.valid;
};
// on form "reset" event
document.forms[0].onreset = function (e) {
validator.reset();
};
// stuff related ONLY for this demo page:
$('.toggleValidationTooltips').change(function () {
validator.settings.alerts = !this.checked;
if (this.checked)
$('form .alert').remove();
}).prop('checked', false);
</script>
<!-- jQuery --> <!-- jQuery -->
<script src="../vendors/jquery/dist/jquery.min.js"></script> <script src="../vendors/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap --> <!-- Bootstrap -->
@ -414,10 +452,11 @@
<!-- NProgress --> <!-- NProgress -->
<script src="../vendors/nprogress/nprogress.js"></script> <script src="../vendors/nprogress/nprogress.js"></script>
<!-- validator --> <!-- validator -->
<script src="../vendors/validator/validator.js"></script> <!-- <script src="../vendors/validator/validator.js"></script> -->
<!-- Custom Theme Scripts --> <!-- Custom Theme Scripts -->
<script src="../build/js/custom.min.js"></script> <script src="../build/js/custom.min.js"></script>
</body> </body>
</html> </html>

View file

@ -829,7 +829,7 @@
<thead> <thead>
<tr> <tr>
<th> <th>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</th> </th>
<th>Name</th> <th>Name</th>
<th>Position</th> <th>Position</th>
@ -844,7 +844,7 @@
<tbody> <tbody>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Tiger Nixon</td> <td>Tiger Nixon</td>
<td>System Architect</td> <td>System Architect</td>
@ -855,7 +855,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Garrett Winters</td> <td>Garrett Winters</td>
<td>Accountant</td> <td>Accountant</td>
@ -866,7 +866,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Ashton Cox</td> <td>Ashton Cox</td>
<td>Junior Technical Author</td> <td>Junior Technical Author</td>
@ -877,7 +877,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Cedric Kelly</td> <td>Cedric Kelly</td>
<td>Senior Javascript Developer</td> <td>Senior Javascript Developer</td>
@ -888,7 +888,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Airi Satou</td> <td>Airi Satou</td>
<td>Accountant</td> <td>Accountant</td>
@ -899,7 +899,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Brielle Williamson</td> <td>Brielle Williamson</td>
<td>Integration Specialist</td> <td>Integration Specialist</td>
@ -910,7 +910,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Herrod Chandler</td> <td>Herrod Chandler</td>
<td>Sales Assistant</td> <td>Sales Assistant</td>
@ -921,7 +921,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Rhona Davidson</td> <td>Rhona Davidson</td>
<td>Integration Specialist</td> <td>Integration Specialist</td>
@ -932,7 +932,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Colleen Hurst</td> <td>Colleen Hurst</td>
<td>Javascript Developer</td> <td>Javascript Developer</td>
@ -943,7 +943,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Sonya Frost</td> <td>Sonya Frost</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -954,7 +954,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jena Gaines</td> <td>Jena Gaines</td>
<td>Office Manager</td> <td>Office Manager</td>
@ -965,7 +965,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Quinn Flynn</td> <td>Quinn Flynn</td>
<td>Support Lead</td> <td>Support Lead</td>
@ -976,7 +976,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Charde Marshall</td> <td>Charde Marshall</td>
<td>Regional Director</td> <td>Regional Director</td>
@ -987,7 +987,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Haley Kennedy</td> <td>Haley Kennedy</td>
<td>Senior Marketing Designer</td> <td>Senior Marketing Designer</td>
@ -998,7 +998,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Tatyana Fitzpatrick</td> <td>Tatyana Fitzpatrick</td>
<td>Regional Director</td> <td>Regional Director</td>
@ -1009,7 +1009,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Michael Silva</td> <td>Michael Silva</td>
<td>Marketing Designer</td> <td>Marketing Designer</td>
@ -1020,7 +1020,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Paul Byrd</td> <td>Paul Byrd</td>
<td>Chief Financial Officer (CFO)</td> <td>Chief Financial Officer (CFO)</td>
@ -1031,7 +1031,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Gloria Little</td> <td>Gloria Little</td>
<td>Systems Administrator</td> <td>Systems Administrator</td>
@ -1042,7 +1042,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Bradley Greer</td> <td>Bradley Greer</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -1053,7 +1053,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Dai Rios</td> <td>Dai Rios</td>
<td>Personnel Lead</td> <td>Personnel Lead</td>
@ -1064,7 +1064,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jenette Caldwell</td> <td>Jenette Caldwell</td>
<td>Development Lead</td> <td>Development Lead</td>
@ -1075,7 +1075,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Yuri Berry</td> <td>Yuri Berry</td>
<td>Chief Marketing Officer (CMO)</td> <td>Chief Marketing Officer (CMO)</td>
@ -1086,7 +1086,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Caesar Vance</td> <td>Caesar Vance</td>
<td>Pre-Sales Support</td> <td>Pre-Sales Support</td>
@ -1097,7 +1097,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Doris Wilder</td> <td>Doris Wilder</td>
<td>Sales Assistant</td> <td>Sales Assistant</td>
@ -1108,7 +1108,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Angelica Ramos</td> <td>Angelica Ramos</td>
<td>Chief Executive Officer (CEO)</td> <td>Chief Executive Officer (CEO)</td>
@ -1119,7 +1119,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Gavin Joyce</td> <td>Gavin Joyce</td>
<td>Developer</td> <td>Developer</td>
@ -1130,7 +1130,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jennifer Chang</td> <td>Jennifer Chang</td>
<td>Regional Director</td> <td>Regional Director</td>
@ -1141,7 +1141,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Brenden Wagner</td> <td>Brenden Wagner</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -1152,7 +1152,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Fiona Green</td> <td>Fiona Green</td>
<td>Chief Operating Officer (COO)</td> <td>Chief Operating Officer (COO)</td>
@ -1163,7 +1163,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Shou Itou</td> <td>Shou Itou</td>
<td>Regional Marketing</td> <td>Regional Marketing</td>
@ -1174,7 +1174,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Michelle House</td> <td>Michelle House</td>
<td>Integration Specialist</td> <td>Integration Specialist</td>
@ -1185,7 +1185,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Suki Burks</td> <td>Suki Burks</td>
<td>Developer</td> <td>Developer</td>
@ -1196,7 +1196,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Prescott Bartlett</td> <td>Prescott Bartlett</td>
<td>Technical Author</td> <td>Technical Author</td>
@ -1207,7 +1207,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Gavin Cortez</td> <td>Gavin Cortez</td>
<td>Team Leader</td> <td>Team Leader</td>
@ -1218,7 +1218,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Martena Mccray</td> <td>Martena Mccray</td>
<td>Post-Sales support</td> <td>Post-Sales support</td>
@ -1229,7 +1229,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Unity Butler</td> <td>Unity Butler</td>
<td>Marketing Designer</td> <td>Marketing Designer</td>
@ -1240,7 +1240,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Howard Hatfield</td> <td>Howard Hatfield</td>
<td>Office Manager</td> <td>Office Manager</td>
@ -1251,7 +1251,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Hope Fuentes</td> <td>Hope Fuentes</td>
<td>Secretary</td> <td>Secretary</td>
@ -1262,7 +1262,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Vivian Harrell</td> <td>Vivian Harrell</td>
<td>Financial Controller</td> <td>Financial Controller</td>
@ -1273,7 +1273,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Timothy Mooney</td> <td>Timothy Mooney</td>
<td>Office Manager</td> <td>Office Manager</td>
@ -1284,7 +1284,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jackson Bradshaw</td> <td>Jackson Bradshaw</td>
<td>Director</td> <td>Director</td>
@ -1295,7 +1295,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Olivia Liang</td> <td>Olivia Liang</td>
<td>Support Engineer</td> <td>Support Engineer</td>
@ -1306,7 +1306,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Bruno Nash</td> <td>Bruno Nash</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -1317,7 +1317,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Sakura Yamamoto</td> <td>Sakura Yamamoto</td>
<td>Support Engineer</td> <td>Support Engineer</td>
@ -1328,7 +1328,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Thor Walton</td> <td>Thor Walton</td>
<td>Developer</td> <td>Developer</td>
@ -1339,7 +1339,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Finn Camacho</td> <td>Finn Camacho</td>
<td>Support Engineer</td> <td>Support Engineer</td>
@ -1350,7 +1350,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Serge Baldwin</td> <td>Serge Baldwin</td>
<td>Data Coordinator</td> <td>Data Coordinator</td>
@ -1361,7 +1361,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Zenaida Frank</td> <td>Zenaida Frank</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -1372,7 +1372,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Zorita Serrano</td> <td>Zorita Serrano</td>
<td>Software Engineer</td> <td>Software Engineer</td>
@ -1383,7 +1383,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jennifer Acosta</td> <td>Jennifer Acosta</td>
<td>Junior Javascript Developer</td> <td>Junior Javascript Developer</td>
@ -1394,7 +1394,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Cara Stevens</td> <td>Cara Stevens</td>
<td>Sales Assistant</td> <td>Sales Assistant</td>
@ -1405,7 +1405,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Hermione Butler</td> <td>Hermione Butler</td>
<td>Regional Director</td> <td>Regional Director</td>
@ -1416,7 +1416,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Lael Greer</td> <td>Lael Greer</td>
<td>Systems Administrator</td> <td>Systems Administrator</td>
@ -1427,7 +1427,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Jonas Alexander</td> <td>Jonas Alexander</td>
<td>Developer</td> <td>Developer</td>
@ -1438,7 +1438,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Shad Decker</td> <td>Shad Decker</td>
<td>Regional Director</td> <td>Regional Director</td>
@ -1449,7 +1449,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Michael Bruce</td> <td>Michael Bruce</td>
<td>Javascript Developer</td> <td>Javascript Developer</td>
@ -1460,7 +1460,7 @@
</tr> </tr>
<tr> <tr>
<td> <td>
<th><input type="checkbox" id="check-all" class="flat"></th> <th><input type="checkbox" id="check-all" ></th>
</td> </td>
<td>Donna Snider</td> <td>Donna Snider</td>
<td>Customer Support</td> <td>Customer Support</td>

View file

@ -1,14 +1,14 @@
{ {
"name": "validator", "name": "validator",
"homepage": "https://github.com/yairEO/validator", "homepage": "https://github.com/yairEO/validator",
"version": "1.1.0", "version": "3.3.5",
"_release": "1.1.0", "_release": "3.3.5",
"_resolution": { "_resolution": {
"type": "version", "type": "version",
"tag": "1.1.0", "tag": "3.3.5",
"commit": "f855eb37c626f2ad712583d25afdd30147a40d8e" "commit": "01a570d68fa748f87a6a90166f157a64225e9e4d"
}, },
"_source": "https://github.com/yairEO/validator.git", "_source": "https://github.com/yairEO/validator.git",
"_target": "^1.0.6", "_target": "^3.3.5",
"_originalSource": "https://github.com/yairEO/validator.git" "_originalSource": "https://github.com/yairEO/validator.git"
} }

View file

@ -161,3 +161,4 @@ pip-log.txt
# Mac crap # Mac crap
.DS_Store .DS_Store
/.npmrc

View file

@ -1,10 +1,10 @@
validator validator
========= =========
The javascript validation code is based on jQuery. The Validator is cross-browser and will give you the power to use future-proof input types such as tel, email, number, date, and url. I can sum this as a template for creating web forms. The Validator is cross-browser and will give you the power to use future-proof input types such as
`tel`, `email`, `number`, `date`, `time`, `checkbox` and `url`.
In the semantic point-of-view, I believe that this method is very clean and…appropriate. This is how forms should be, IMHO.
[DEMO PAGE](http://yaireo.github.io/validator) # [DEMO PAGE](http://yaireo.github.io/validator)
### Why should you use this? ### Why should you use this?
@ -12,7 +12,7 @@ In the semantic point-of-view, I believe that this method is very clean and…ap
* Deals with all sorts of edge cases * Deals with all sorts of edge cases
* Utilize new HTML5 types for unsupported browsers * Utilize new HTML5 types for unsupported browsers
* Flexible error messaging system * Flexible error messaging system
* Light-weight (10kb + comments) * Light-weight (19kb + comments, unminified)
## Validation types support ## Validation types support
HTML5 offers a wide selection of input types. I saw no need to support them all, for example, a checkbox should not be validated as required because why wouldnt it be checked in the first place when the form is rendered? HTML5 offers a wide selection of input types. I saw no need to support them all, for example, a checkbox should not be validated as required because why wouldnt it be checked in the first place when the form is rendered?
@ -25,26 +25,24 @@ These input types can be validated by the the JS for `<input type='foo' name
* Password * Password
* Number * Number
* Date * Date
* Time
* URL * URL
* Search * Search
* File * File
* Tel * Tel
* Checkbox * Checkbox
* Hidden Hidden fields can also have the required attribute * Select
The below form elements are also supported:
* Select Useing a required class because there is no such attribute for select element
* Textarea * Textarea
* Hidden Hidden fields can also have the required attribute
## Basic semantics ## Basic semantics
<form action="" method="post" novalidate> <form action="" method="post" novalidate>
<fieldset> <fieldset>
<div class="item"> <div class="field">
<label> <label>
<span>Name</span> <span>Name</span>
<input data-validate-lengthRange="6" data-validate-words="2" name="name" placeholder="ex. John f. Kennedy" required="required" type="text" /> <input data-validate-length-range="6" data-validate-words="2" name="name" placeholder="ex. John f. Kennedy" required="required" type="text" />
</label> </label>
<div class='tooltip help'> <div class='tooltip help'>
<span>?</span> <span>?</span>
@ -54,7 +52,7 @@ The below form elements are also supported:
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>email</span> <span>email</span>
<input name="email" required="required" type="email" /> <input name="email" required="required" type="email" />
@ -64,8 +62,8 @@ The below form elements are also supported:
### Explaining the DOM ### Explaining the DOM
First, obviously, there is a Form element with the novalidate attribute to make sure to disable the native HTML5 validations (which currently suck). proceeding it there is a Fieldset element which is not a must, but acts as a “binding” box for a group of fields that are under the same “category”. For bigger forms there are many times field groups that are visually separated from each other for example. Now, we treat every form field element the user interacts with, whatsoever, as an “item”, and therefor these “items” will be wraped with `<div class='item'>`. This isolation gives great powers. First, obviously, there is a Form element with the novalidate attribute to make sure to disable the native HTML5 validations (which currently suck). proceeding it there is a Fieldset element which is not a must, but acts as a “binding” box for a group of fields that are under the same “category”. For bigger forms there are many times field groups that are visually separated from each other for example. Now, we treat every form field element the user interacts with, whatsoever, as an “field”, and therefor these “fields” will be wraped with `<div class='field'>`. This isolation gives great powers.
Next, inside an item, there will typically be an input or select or something of the sort, so they are put inside a `<label>` element, to get rid of the (annoying) for attribute, on the label (which also require us to give an ID to the form field element), and now when a user clicks on the label, the field will get focused. great. Going back to the labels text itself, we wrap it with a `<span>` to have control over its style. Next, inside an field, there will typically be an input or select or something of the sort, so they are put inside a `<label>` element, to get rid of the (annoying) for attribute, on the label (which also require us to give an ID to the form field element), and now when a user clicks on the label, the field will get focused. great. Going back to the labels text itself, we wrap it with a `<span>` to have control over its style.
The whole approach here is to define each form field (input, select, whatever) as much as possible with HTML5 attributes and also with custom attributes. The whole approach here is to define each form field (input, select, whatever) as much as possible with HTML5 attributes and also with custom attributes.
@ -77,83 +75,134 @@ The whole approach here is to define each form field (input, select, whatever) a
| data-validate-words | Defines the minimum amount of words for this field | | data-validate-words | Defines the minimum amount of words for this field |
| data-validate-length | Defines the length allowed for the field (after trim). Example value: `7,11` (field can only have 7 or 11 characters). you can add how many allowed lengths you wish | | data-validate-length | Defines the length allowed for the field (after trim). Example value: `7,11` (field can only have 7 or 11 characters). you can add how many allowed lengths you wish |
| data-validate-length-range | Defines the minimum and/or maximum number of chars in the field (after trim). value can be `4,8` for example, or just `4` to set minimum chars only | | data-validate-length-range | Defines the minimum and/or maximum number of chars in the field (after trim). value can be `4,8` for example, or just `4` to set minimum chars only |
| data-validate-linked | Defines the field which the current fields value (the attribute is set on) should be compared to | | data-validate-linked | Defines the field which the current fields value (the attribute is set on) should be compared to. Value can be a selector or another input's `name` attribute's value |
| data-validate-minmax | For type `number` only. Defines the minimum and/or maximum value that can be in that field | | data-validate-minmax | For type `number` only. Defines the minimum and/or maximum value that can be in that field |
### Optional fields ### Optional fields
There is also support for optional fields, which are not validated, unless they have a value. The support for this feature is done by adding a class “optional” to a form element. Note that this should not be done along side the “required” attribute. There is also support for optional fields, which are not validated, unless they have a value. The support for this feature is done by adding a class `optional` to a form element. Note that this should not be done along side the “required” attribute.
## Error messages ## Error messages
The validator function holds a messages object called "message", which itself holds all the error messages being shown to the user for all sort of validation errors. This is the object which holds all the texts used by the form validator:
message = { {
invalid : 'invalid input', invalid : 'inupt is not as expected',
short : 'input is too short',
long : 'input is too long',
checked : 'must be checked',
empty : 'please put something here', empty : 'please put something here',
min : 'input is too short', select : 'Please select an option',
max : 'input is too long',
number_min : 'too low', number_min : 'too low',
number_max : 'too high', number_max : 'too high',
url : 'invalid URL', url : 'invalid URL',
number : 'not a number', number : 'not a number',
email : 'email address is invalid', email : 'email address is invalid',
email_repeat : 'emails do not match', email_repeat : 'emails do not match',
date : 'invalid date',
time : 'invalid time',
password_repeat : 'passwords do not match', password_repeat : 'passwords do not match',
repeat : 'no match', no_match : 'no match',
complete : 'input is not complete', complete : 'input is not complete'
select : 'Please select an option' }
};
This object can be extended easily. The idea is to extend it with new keys which represent the name of the field you want the message to be linked to, and that custom message appear as the `general error` one. Default messages can be over-ride. This object can be extended easily. The idea is to extend it with new keys which represent the name of the field you want the message to be linked to, and that custom message appear as the `general error` one. Default messages can be over-ride.
Example: for a given type date field, lets set a custom (general error) message like so: Example: for a given type date field, lets set a custom (general error) message like so:
`validator.message['date'] = 'not a real date';`
Error messages can be disabled: // set custom text on initialization:
`validator.defaults.alerts = false;` var validator = new FormValidator({
texts : {
date:'not a real date'
}
});
// or post-initialization
var validator = new FormValidator();
validator.texts.date = 'not a real date';
Error messages (per field) can be disabled:
validator = new FormValidator({
alerts:false
});
// or by:
var validator = new FormValidator();
validator.settings.alerts = false;
## Binding the validation to a form ## Binding the validation to a form
There are 2 ways to validate form fields, one is on the submit event of the form itself, then all the fields are evaluated one by one. The other method is by binding the checkField function itself to each field, for events like “Blur”, “Change” or whatever event you wish (I prefer on Blur). There are two ways to validate form fields, one is on the submit event of the form itself, then all the fields are evaluated one by one.
The other method is by binding the `checkField` function itself to each field, for events like `Blur`, `Change` or whatever event you wish (I prefer on Blur).
### Usage example - validate on submit ### Usage example - validate on submit
A generic callback function using jQuery to have the form validated on the **Submit** event. You can also include your own personal validations before the **checkAll()** call. A generic callback function to have the form validated on the **Submit** event. You can also include your own personal validations before the **checkAll()** call.
$('form').submit(function(e){ var validator = new FormValidator();
e.preventDefault(); // select your "form" element from the DOM and attach an "onsubmit" event handler to it:
var submit = true; document.forms[0].onsubmit = function(e){
// you can put your own custom validations below var validatorResult = validator.checkAll(this);
// check all the rerquired fields return !!validatorResult.valid;
if( !validator.checkAll( $(this) ) ) };
submit = false;
if( submit ) ### Usage example - validate on field blur/input/change events
this.submit(); Check every field (using event Capture)
return false; var validator = new FormValidator();
})
###Usage example - validate on field blur event (out of focus) document.forms[0].addEventListener('blur', function(e){
Check every field once it looses focus (onBlur) event validator.checkField(e.target)
}, true);
$('form').on('blur', 'input[required]', validator.checkField); document.forms[0].addEventListener('input', function(e){
validator.checkField(e.target);
}, true);
## Tooltips document.forms[0].addEventListener('change', function(e){
validator.checkField(e.target)
}, true);
The helper tooltips **&lt;div class='tooltip help'&gt;**, which work using pure CSS, are element which holds a small **'?'** icon and when hovered over with the mouse, reveals a text explaining what the field “item” is about or for example, what the allowed input format is. Utilize the internal events' binding system; pass in the settings the `events` property and assign it an array which states which events should be inputs be validated for. For a single events, a string may be paassed instead of an Array:
var validator = new FormValidator( document.forms[0], {
"events" : ['blur', 'input', 'change'] // for a single one, just pass a string, ex: "blur"
});
In case the form is not yet ready, the events maybe be binded later, when the form is ready, using the internal `events` method for a `validator` instance:
// validate fields on these events:
var validator = new FormValidator(document.forms[0]); // the "<form>" element should be passed when the instance is created or passed to the "events" method below (as the 2nd parameter)
// wait for the form, or its' fields, to be ready (for whatever reason), and then bind the events as follows:
validator.events(['blur', 'input', 'change']);
## Tooltips (for each field which did not validate)
The helper tooltips **&lt;div class='tooltip help'&gt;**, which work using pure CSS, are element which holds a small **'?'** icon and when hovered over with the mouse, reveals a text explaining what the field “field” is about or for example, what the allowed input format is.
## Classes ## Classes
`validator.defaults.classes` object can be modified with these classes: `validator.settings.classes` object can be modified:
item : 'item', // class for each input wrapper var validatorClasses = {
field : 'field', // class for each input wrapper
alert : 'alert', // call on the alert tooltip alert : 'alert', // call on the alert tooltip
bad : 'bad' // classes for bad input bad : 'bad' // classes for bad input
};
## Bonos multifields validator = new FormValidator(null, {classes:validatorClasses});
// or
validator = new FormValidator();
validator.settings.classes.bad = 'error';
## Bonus multifields
I have a cool feature I wrote which I call “multifields”. These are fields which are often use as to input a credit card or a serial number, and are actually a bunch of input fields which are “connected” to each other, and treated as one. You can see it in the demo page, and its included in multifield.js file. I have a cool feature I wrote which I call “multifields”. These are fields which are often use as to input a credit card or a serial number, and are actually a bunch of input fields which are “connected” to each other, and treated as one. You can see it in the demo page, and its included in multifield.js file.

View file

@ -44,23 +44,23 @@ input:focus, textarea:focus{ border-color:#AAA; }
input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance:none; margin:0; } input[type=number]::-webkit-inner-spin-button, input[type=number]::-webkit-outer-spin-button { -webkit-appearance:none; margin:0; }
input[type=checkbox]{ width:auto; border:none; bottom:-1px; cursor:pointer; margin:2px 8px 0 0; position:relative; transform:scale(1.2); } input[type=checkbox]{ width:auto; border:none; bottom:-1px; cursor:pointer; margin:2px 8px 0 0; position:relative; transform:scale(1.2); }
button[type=submit]{ font-size:1.1em; padding:5px 25px; } button{ font-size:1.1em; padding:5px 25px; }
/* Tooltips helpers */ /* Tooltips helpers */
.item .tooltip{ float:left; top:2px; left:7px; position:relative; z-index:2; } .field .tooltip{ float:left; top:2px; left:7px; position:relative; z-index:2; }
.item .tooltip:hover{ z-index:3; } .field .tooltip:hover{ z-index:3; }
.item .tooltip > span{ display:inline-block; width:15px; height:15px; line-height:15px; font-size:0.9em; font-weight:bold; text-align:center; color:#FFF; cursor:help; background-color:#00AEEF; position:relative; border-radius:10px; } .field .tooltip > span{ display:inline-block; width:15px; height:15px; line-height:15px; font-size:0.9em; font-weight:bold; text-align:center; color:#FFF; cursor:help; background-color:#00AEEF; position:relative; border-radius:10px; }
.item .tooltip .content{ opacity:0; width:200px; background-color:#333; color:#FFF; font-size:0.9em; position:absolute; top:0; left:20px; padding:8px; border-radius:6px; pointer-events:none; transition:0.2s cubic-bezier(0.1, 0.1, 0.25, 2); -webkit-transition:0.3s cubic-bezier(0.1, 0.2, 0.5, 2.2); -moz-transition:0.3s cubic-bezier(0.1, 0.2, 0.5, 2.2); } .field .tooltip .content{ opacity:0; width:200px; background-color:#333; color:#FFF; font-size:0.9em; position:absolute; top:0; left:20px; padding:8px; border-radius:6px; pointer-events:none; transition:0.2s cubic-bezier(0.1, 0.1, 0.25, 2); -webkit-transition:0.3s cubic-bezier(0.1, 0.2, 0.5, 2.2); -moz-transition:0.3s cubic-bezier(0.1, 0.2, 0.5, 2.2); }
.item .tooltip p{ padding:0; } .field .tooltip p{ padding:0; }
.item .tooltip.down .content{ left:auto; right:0; top:30px; } .field .tooltip.down .content{ left:auto; right:0; top:30px; }
.item .tooltip:hover .content{ opacity:1; left:36px; } .field .tooltip:hover .content{ opacity:1; left:36px; }
.item .tooltip .content b{ height:0; width:0; border-color:#333 #333 transparent transparent; border-style:solid; border-width:9px 7px; position:absolute; left:-14px; top:8px; } .field .tooltip .content b{ height:0; width:0; border-color:#333 #333 transparent transparent; border-style:solid; border-width:9px 7px; position:absolute; left:-14px; top:8px; }
.item .tooltip.down .content b{ left:auto; right:6px; top:-10px; border-width:5px; border-color:transparent #333 #333 transparent; } .field .tooltip.down .content b{ left:auto; right:6px; top:-10px; border-width:5px; border-color:transparent #333 #333 transparent; }
/* alerts (when validation fails) */ /* alerts (when validation fails) */
.item .alert{ float:left; margin:-2px 0 0 20px; padding:3px 10px; color:#FFF; border-radius:3px 4px 4px 3px; background-color:#CE5454; max-width:170px; white-space:pre; position:relative; left:-15px; opacity:0; z-index:1; transition:0.15s ease-out; } .field .alert{ float:left; margin:-2px 0 0 20px; padding:3px 10px; color:#FFF; border-radius:3px 4px 4px 3px; background-color:#CE5454; max-width:170px; white-space:pre; position:relative; left:-15px; opacity:0; z-index:1; transition:0.15s ease-out; }
.item .alert::after{ content:''; display:block; height:0; width:0; border-color:transparent #CE5454 transparent transparent; border-style:solid; border-width:11px 7px; position:absolute; left:-13px; top:1px; } .field .alert::after{ content:''; display:block; height:0; width:0; border-color:transparent #CE5454 transparent transparent; border-style:solid; border-width:11px 7px; position:absolute; left:-13px; top:1px; }
.item.bad .alert{ left:0; opacity:1; } .field.bad .alert{ left:0; opacity:1; }
@keyframes shake{ @keyframes shake{
@ -77,47 +77,47 @@ button[type=submit]{ font-size:1.1em; padding:5px 25px; }
} }
form fieldset{ clear:both; margin:0 0 10px 0; } form fieldset{ clear:both; margin:0 0 10px 0; }
form .item{ padding:5px 0; position:relative; height:2em; } form .field{ padding:5px 0; position:relative; height:2em; }
form .item.items{ height:auto; } form .field.fields{ height:auto; }
.item label, .item .label{ float:left; cursor:pointer; } .field label, .field .label{ cursor:pointer; }
.item label span, .item .label{ float:left; width:160px; text-transform:capitalize; line-height:2em; } .field label > span:first-child, .field .label{ float:left; width:160px; text-transform:capitalize; line-height:2em; }
.item input, .item textarea{ float:left; padding:3px 4px; width:210px; -webkit-transition:0.2s; -moz-transition:0.2s; transition:0.2s; } .field input, .field textarea{ float:left; padding:3px 4px; width:210px; -webkit-transition:0.2s; -moz-transition:0.2s; transition:0.2s; }
.item input[type=checkbox]{ width:auto; } .field input[type=checkbox]{ width:auto; }
.label ~ label{ vertical-align:middle; margin:0.3em 1.2em 0 0; } .label ~ label{ vertical-align:middle; margin:0.3em 1.2em 0 0; }
.item input.short{ width:90px; } .field input.short{ width:90px; }
.item input:focus:not([type="checkbox"]), .item textarea:focus{ box-shadow:0 0 4px #00AEEF; border:1px solid #00AEEF; } .field input:focus:not([type="checkbox"]), .field textarea:focus{ box-shadow:0 0 4px #00AEEF; border:1px solid #00AEEF; }
.item textarea{ } .field textarea{ }
.item select{ float:left; width:220px; padding:2px 0; margin:0; border:1px solid #CCC; text-transform:capitalize; } .field select{ float:left; width:220px; padding:2px 0; margin:0; border:1px solid #CCC; text-transform:capitalize; }
.item select option{ padding:1px; } .field select option{ padding:1px; }
.item > .extra{ float:left; font-size:0.9em; color:#999; line-height:2em; margin-left:13px; } .field > .extra{ float:left; font-size:0.9em; color:#999; line-height:2em; margin-left:13px; }
.item.multi .input{ float:left; } .field.multi .input{ float:left; }
.item.multi input{ float:left; margin-right:5px; width:35px; text-align:center; } .field.multi input{ float:left; margin-right:5px; width:35px; text-align:center; }
form .item.multi input:nth-last-child(-n+2){ margin:0; } form .field.multi input:nth-last-child(-n+2){ margin:0; }
.item.items input{ border-top:5px solid #E1E1E1; margin:0 0 0 160px; } .field.fields input{ border-top:5px solid #E1E1E1; margin:0 0 0 160px; }
.bad input, .bad input,
.bad select, .bad select,
.bad textarea{ border:1px solid #CE5454; box-shadow:0 0 4px -2px #CE5454; position:relative; left:0; -moz-animation:.7s 1 shake linear; -webkit-animation:0.7s 1 shake linear; } .bad textarea{ border:1px solid #CE5454; box-shadow:0 0 4px -2px #CE5454; position:relative; left:0; -moz-animation:.4s 1 shake ease; -webkit-animation:0.4s 1 shake ease; }
/* mode2 - where the label's text is above the field and not next to it /* mode2 - where the label's text is above the field and not next to it
--------------------------------------------------------------------------- */ --------------------------------------------------------------------------- */
.mode2 .item{ float:left; clear:left; margin-bottom:30px; height:auto; padding:0; zoom:1; } .mode2 .field{ float:left; clear:left; margin-bottom:30px; height:auto; padding:0; zoom:1; }
.mode2 .item.bad{ margin-bottom:8px; } .mode2 .field.bad{ margin-bottom:8px; }
.mode2 .item::before, .mode2 .item::after{ content:''; display:table; } .mode2 .field::before, .mode2 .field::after{ content:''; display:table; }
.mode2 .item::after{ clear:both; } .mode2 .field::after{ clear:both; }
.mode2 .item label{ } .mode2 .field label{ }
.mode2 .item label span{ float:none; display:block; line-height:inherit; } .mode2 .field label span{ float:none; display:block; line-height:inherit; }
.mode2 .item input:not(type="checkbox"), .item textarea{ width:250px; margin:0; } .mode2 .field input:not(type="checkbox"), .field textarea{ width:250px; margin:0; }
.mode2 .item textarea{ width:350px; margin:0; } .mode2 .field textarea{ width:350px; margin:0; }
.mode2 .item select{ width:260px; float:none; } .mode2 .field select{ width:260px; float:none; }
.mode2 .item.multi label{ float:none; } .mode2 .field.multi label{ float:none; }
.mode2 .item.multi input{ float:left; margin-right:5px; width:35px; text-align:center; } .mode2 .field.multi input{ float:left; margin-right:5px; width:35px; text-align:center; }
.mode2 .item .tooltip{ left:auto; position:absolute; right:-22px; top:19px; } .mode2 .field .tooltip{ left:auto; position:absolute; right:-22px; top:19px; }
.mode2 .item .alert::after{ display:none; } .mode2 .field .alert::after{ display:none; }
.mode2 .item .alert{ float:none; clear:left; margin:0; padding:0 5px; border-radius:0 0 3px 3px; max-width:100%; height:22px; line-height:1.8em; } .mode2 .field .alert{ float:none; clear:left; margin:0; padding:0 5px; border-radius:0 0 3px 3px; max-width:100%; height:22px; line-height:1.8em; }
.mode2 .item > .extra{ position:absolute; right:0; } .mode2 .field > .extra{ position:absolute; right:0; }

View file

@ -7,8 +7,8 @@
<link rel="stylesheet" href="fv.css" type="text/css" /> <link rel="stylesheet" href="fv.css" type="text/css" />
<!--[if IE]> <!--[if IE]>
<style> <style>
.item .tooltip .content{ display:none; opacity:1; } .field .tooltip .content{ display:none; opacity:1; }
.item .tooltip:hover .content{ display:block; } .field .tooltip:hover .content{ display:block; }
</style> </style>
<![endif]--> <![endif]-->
</head> </head>
@ -16,20 +16,20 @@
<a class='btn github' href='https://github.com/yairEO/validator'>Github</a> <a class='btn github' href='https://github.com/yairEO/validator'>Github</a>
<div id='wrap'> <div id='wrap'>
<div class='options'> <div class='options'>
<label> <!-- <label>
<input type='checkbox' id='vfields' /> <input type='checkbox' id='vfields' />
Vertical orientation Vertical orientation
</label> </label> -->
<label> <label>
<input type='checkbox' id='alerts' /> <input type='checkbox' class='toggleValidationTooltips' />
Disable alerts Disable vlidation tooltips
</label> </label>
</div> </div>
<h1 title='how forms should be done.'>Forms: validation, styling &amp; semantics</h1> <h1 title='how forms should be done.'>Forms: validation, styling &amp; semantics</h1>
<section class='form'> <section class='form'>
<form action="" method="post" novalidate> <form action="" method="post" novalidate>
<fieldset> <fieldset>
<div class="item"> <div class="field">
<label> <label>
<span>Name</span> <span>Name</span>
<input data-validate-length-range="6" data-validate-words="2" name="name" placeholder="ex. John f. Kennedy" required="required" /> <input data-validate-length-range="6" data-validate-words="2" name="name" placeholder="ex. John f. Kennedy" required="required" />
@ -42,21 +42,21 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Occupation</span> <span>Occupation</span>
<input class='optional' name="occupation" data-validate-length-range="5,20" type="text" /> <input class='optional' name="occupation" data-validate-length-range="5,15" type="text" />
</label> </label>
<div class='tooltip help'> <div class='tooltip help'>
<span>?</span> <span>?</span>
<div class='content'> <div class='content'>
<b></b> <b></b>
<p>An optional field. This field is only validated when it has a value.<br /><em>Minimum 5 chars for this example.</em></p> <p>An optional field. This field is only validated when it has a value.<br /><em>Minimum 5 chars, maximum 15</em></p>
</div> </div>
</div> </div>
<span class='extra'>(optional)</span> <span class='extra'>(optional)</span>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>HTML5 Regex</span> <span>HTML5 Regex</span>
<!--<input required="required" type="text" pattern='\d+' />--> <!--<input required="required" type="text" pattern='\d+' />-->
@ -70,19 +70,19 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>email</span> <span>email</span>
<input name="email" class='email' required="required" type="email" /> <input name="email" class='email' required="required" type="email" />
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Confirm email address</span> <span>Confirm email address</span>
<input type="email" class='email' name="confirm_email" data-validate-linked='email' required='required'> <input type="email" class='email' name="confirm_email" data-validate-linked='email' required='required'>
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Number</span> <span>Number</span>
<input type="number" class='number' name="number" data-validate-minmax="10,100" required='required'> <input type="number" class='number' name="number" data-validate-minmax="10,100" required='required'>
@ -95,13 +95,26 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Date</span> <span>Date</span>
<input class='date' type="date" name="date" required='required'> <input class='date' type="date" name="date" required='required'>
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label>
<span>Time</span>
<input class='time' type="time" name="time" required='required'>
<div class='tooltip help'>
<span>?</span>
<div class='content'>
<b></b>
<p>Format should be: XX:XX</p>
</div>
</div>
</label>
</div>
<div class="field">
<label> <label>
<span>Password</span> <span>Password</span>
<input type="password" name="password" data-validate-length="6,8" required='required'> <input type="password" name="password" data-validate-length="6,8" required='required'>
@ -114,13 +127,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Repeat password</span> <span>Repeat password</span>
<input type="password" name="password2" data-validate-linked='password' required='required'> <input type="password" name="password2" data-validate-linked='password' required='required'>
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Telephone</span> <span>Telephone</span>
<input type="tel" class='tel' name="phone" required='required' data-validate-length-range="8,20"> <input type="tel" class='tel' name="phone" required='required' data-validate-length-range="8,20">
@ -133,11 +146,11 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Drop down selection</span> <span>Drop down selection</span>
<select class="required" name="dropdown"> <select required name="dropdown">
<option value="">-- none --</option> <option value="">-- please select --</option>
<option value="o1">Option 1</option> <option value="o1">Option 1</option>
<option value="o2">Option 2</option> <option value="o2">Option 2</option>
<option value="o3">Option 3</option> <option value="o3">Option 3</option>
@ -151,21 +164,30 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>url</span> <span>url</span>
<input name="url" placeholder="http://www.website.com" required="required" type="url" /> <input name="url" placeholder="http://www.website.com" required="required" type="url" />
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>Checkboxes</span> <span>Checkbox</span>
<label><input required="required" type="checkbox" />I agree</label> <input required="required" type="checkbox" />
<span>I agree</span>
</label> </label>
</div> </div>
<div class="item multi required"> <div class="field">
<label>
<span>Checkbox</span>
<input type="checkbox" />
<span>Optional Checkbox</span>
</label>
</div>
<div class="field multi required">
<label for='multi_first'> <label for='multi_first'>
<span>Multifield</span> <span>Multifield</span>
</label> </label>
@ -186,13 +208,13 @@
</div> </div>
</div> </div>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>File upload</span> <span>File upload</span>
<input type='file' required> <input type='file' required>
</label> </label>
</div> </div>
<div class="item"> <div class="field">
<label> <label>
<span>message</span> <span>message</span>
<textarea required="required" name='message'></textarea> <textarea required="required" name='message'></textarea>
@ -200,10 +222,15 @@
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset>
<p>There is a hidden "Required" form field below, notice it will not be validated due to its lack of visibility. The reason for this is that sometimes there is a section in a form that is not visible until some action is taken, but you do not want to change all those fields' "required" attributes on-the-fly, so that is why.</p> <p>
There is a hidden "required" form field below, notice it will not be validated due to its lack of visibility.<br>
The reason for this is that sometimes there is a section in a form that is not visible until some user "action" is taken,
and changing form fields to be "required" on-the-fly is undesirable.
</p>
<input name="somethingHidden" required="required" type="text" style='display:none' /> <input name="somethingHidden" required="required" type="text" style='display:none' />
</fieldset> </fieldset>
<button id='send' type='submit'>Submit</button> <button type='submit'>Submit</button>
<button type='reset'>Reset</button>
</form> </form>
</section> </section>
</div> </div>
@ -211,45 +238,30 @@
<script src="multifield.js"></script> <script src="multifield.js"></script>
<script src="validator.js"></script> <script src="validator.js"></script>
<script> <script>
// initialize the validator function // initialize a validator instance from the "FormValidator" constructor.
validator.message['date'] = 'not a real date'; // A "<form>" element is optionally passed as an argument, but is not a must
var validator = new FormValidator({"events" : ['blur', 'input', 'change']}, document.forms[0]);
// validate a field on "blur" event, a 'select' on 'change' event & a '.reuired' classed multifield on 'keyup':
$('form')
.on('blur', 'input[required], input.optional, select.required', validator.checkField)
.on('change', 'select.required', validator.checkField)
.on('keypress', 'input[required][pattern]', validator.keypress);
$('.multi.required') // on form "submit" event
.on('keyup blur', 'input', function(){ document.forms[0].onsubmit = function(e){
validator.checkField.apply( $(this).siblings().last()[0] ); var submit = true,
}); validatorResult = validator.checkAll(this);
// bind the validation to the form submit event console.log(validatorResult);
//$('#send').click('submit');//.prop('disabled', true); return !!validatorResult.valid;
};
$('form').submit(function(e){
e.preventDefault();
var submit = true;
// Validate the form using generic validaing // on form "reset" event
if( !validator.checkAll( $(this) ) ){ document.forms[0].onreset = function(e){
submit = false; validator.reset();
} };
if( submit ) // stuff related ONLY for this demo page:
this.submit(); $('.toggleValidationTooltips').change(function(){
validator.settings.alerts = !this.checked;
return false;
});
/* FOR DEMO ONLY */
$('#vfields').change(function(){
$('form').toggleClass('mode2');
}).prop('checked',false);
$('#alerts').change(function(){
validator.defaults.alerts = (this.checked) ? false : true;
if( this.checked ) if( this.checked )
$('form .alert').remove(); $('form .alert').remove();
}).prop('checked',false); }).prop('checked',false);

22
vendors/validator/package.json vendored Normal file
View file

@ -0,0 +1,22 @@
{
"name" : "@yaireo/validator",
"version" : "3.3.4",
"homepage" : "https://github.com/yairEO/validator",
"description" : "The Validator is cross-browser and will give you the power to use future-proof input types such as `tel`, `email`, `number`, `date`, `time`, `checkbox` and `url`",
"_npmUser" : {
"name" : "vsync",
"email" : "vsync.design@gmail.com"
},
"author" : {
"name" : "Yair Even-Or",
"email" : "vsync.design@gmail.com"
},
"main" : "validator.js",
"repository" : {
"type" : "git",
"url" : "git+https://github.com/yairEO/validator.git"
},
"bugs" : {
"url": "https://github.com/yaireo/validator/issues"
}
}

View file

@ -1,30 +0,0 @@
{
"name": "validator",
"title": "validator",
"description": "The Validator is cross-browser and will give you the power to use future-proof input types such as 'tel', 'email', 'number', 'date', and 'url'. I can sum this as a 'template' for creating web forms. It uses the power of custom 'data' to achieve high flexibility",
"keywords": ["validator", "validation", "form", "input"],
"version": "1.0.6",
"author": {
"name": "Yair Even Or",
"url": "http://dropthebit.com"
},
"maintainers": [
{
"name": "Yair Even Or",
"email": "vsync.design@gmail.com"
}
],
"licenses": [
{
"type": "MIT",
"url": "http://opensource.org/licenses/MIT"
}
],
"bugs": "https://github.com/yairEO/validator/issues",
"homepage": "https://github.com/yairEO/validator",
"docs": "https://github.com/yairEO/validator",
"download": "https://github.com/yairEO/validator",
"dependencies": {
"jquery": ">=1.5"
}
}

View file

@ -1,411 +1,594 @@
/* /*
Validator v1.1.0 Validator v3.3.1
(c) Yair Even Or (c) Yair Even Or
https://github.com/yairEO/validator https://github.com/yairEO/validator
MIT-style license.
*/ */
var validator = (function($){ ;(function(root, factory){
var message, tests, checkField, validate, mark, unmark, field, minmax, defaults, var define = define || {};
validateWords, lengthRange, lengthLimit, pattern, alertTxt, data, if( typeof define === 'function' && define.amd )
email_illegalChars = /[\(\)\<\>\,\;\:\\\/\"\[\]]/, define([], factory);
email_filter = /^.+@.+\..{2,6}$/; // exmaple email "steve@s-i.photo" else if( typeof exports === 'object' && typeof module === 'object' )
module.exports = factory();
else if(typeof exports === 'object')
exports["FormValidator"] = factory();
else
root.FormValidator = factory();
}(this, function(){
function FormValidator( settings, formElm ){
this.data = {}; // holds the form fields' data
/* general text messages this.DOM = {
*/ scope : formElm
message = { };
invalid : 'invalid input',
this.settings = this.extend({}, this.defaults, settings || {});
this.texts = this.extend({}, this.texts, this.settings.texts || {});
this.settings.events && this.events();
}
FormValidator.prototype = {
// Validation error texts
texts : {
invalid : 'inupt is not as expected',
short : 'input is too short',
long : 'input is too long',
checked : 'must be checked', checked : 'must be checked',
empty : 'please put something here', empty : 'please put something here',
min : 'input is too short', select : 'Please select an option',
max : 'input is too long',
number_min : 'too low', number_min : 'too low',
number_max : 'too high', number_max : 'too high',
url : 'invalid URL', url : 'invalid URL',
number : 'not a number', number : 'not a number',
email : 'email address is invalid', email : 'email address is invalid',
email_repeat : 'emails do not match', email_repeat : 'emails do not match',
date : 'invalid date',
time : 'invalid time',
password_repeat : 'passwords do not match', password_repeat : 'passwords do not match',
repeat : 'no match', no_match : 'no match',
complete : 'input is not complete', complete : 'input is not complete'
select : 'Please select an option' },
};
if(!window.console){ // default settings
console={}; defaults : {
console.log=console.warn=function(){ return; }
}
// defaults
defaults = {
alerts : true, alerts : true,
events : false,
regex : {
url : /^(https?:\/\/)?([\w\d\-_]+\.+[A-Za-z]{2,})+\/?/,
phone : /^\+?([0-9]|[-|' '])+$/i,
numeric : /^[0-9]+$/i,
alphanumeric : /^[a-zA-Z0-9]+$/i,
email : {
illegalChars : /[\(\)\<\>\,\;\:\\\/\"\[\]]/,
filter : /^.+@.+\..{2,6}$/ // exmaple email "steve@s-i.photo"
}
},
classes : { classes : {
item : 'item', item : 'field',
alert : 'alert', alert : 'alert',
bad : 'bad' bad : 'bad'
} }
};
/* Tests for each type of field (including Select element)
*/
tests = {
sameAsPlaceholder : function(a){
return $.fn.placeholder && a.attr('placeholder') !== undefined && data.val == a.prop('placeholder');
}, },
hasValue : function(a){
if( !a ){ // Tests (per type)
alertTxt = message.empty; // each test return "true" when passes and a string of error text otherwise
return false; tests : {
} sameAsPlaceholder : function( field, data ){
if( field.getAttribute('placeholder') )
return data.value != field.getAttribute('placeholder') || this.texts.empty;
else
return true; return true;
}, },
hasValue : function( value ){
return value ? true : this.texts.empty;
},
// 'linked' is a special test case for inputs which their values should be equal to each other (ex. confirm email or retype password) // 'linked' is a special test case for inputs which their values should be equal to each other (ex. confirm email or retype password)
linked : function(a,b){ linked : function(a, b, type){
if( b != a ){ if( b != a ){
// choose a specific message or a general one // choose a specific message or a general one
alertTxt = message[data.type + '_repeat'] || message.no_match; return this.texts[type + '_repeat'] || this.texts.no_match;
return false;
} }
return true; return true;
}, },
email : function(a){
if ( !email_filter.test( a ) || a.match( email_illegalChars ) ){ email : function(field, data){
alertTxt = a ? message.email : message.empty; if ( !this.settings.regex.email.filter.test( data.value ) || data.value.match( this.settings.regex.email.illegalChars ) ){
return false; return this.texts.email;
} }
return true; return true;
}, },
// a "skip" will skip some of the tests (needed for keydown validation) // a "skip" will skip some of the tests (needed for keydown validation)
text : function(a, skip){ text : function(field, data){
var that = this;
// make sure there are at least X number of words, each at least 2 chars long. // make sure there are at least X number of words, each at least 2 chars long.
// for example 'john F kenedy' should be at least 2 words and will pass validation // for example 'john F kenedy' should be at least 2 words and will pass validation
if( validateWords ){ if( data.validateWords ){
var words = a.split(' '); var words = data.value.split(' ');
// iterrate on all the words // iterate on all the words
var wordsLength = function(len){ var wordsLength = function(len){
for( var w = words.length; w--; ) for( var w = words.length; w--; )
if( words[w].length < len ) if( words[w].length < len )
return false; return that.texts.short;
return true; return true;
}; };
if( words.length < validateWords || !wordsLength(2) ){ if( words.length < data.validateWords || !wordsLength(2) )
alertTxt = message.complete; return this.texts.complete;
return false;
}
return true; return true;
} }
if( !skip && lengthRange && a.length < lengthRange[0] ){
alertTxt = message.min; if( data.lengthRange && data.value.length < data.lengthRange[0] ){
return false; return this.texts.short;
} }
// check if there is max length & field length is greater than the allowed // check if there is max length & field length is greater than the allowed
if( lengthRange && lengthRange[1] && a.length > lengthRange[1] ){ if( data.lengthRange && data.lengthRange[1] && data.value.length > data.lengthRange[1] ){
alertTxt = message.max; return this.texts.long;
return false;
} }
// check if the field's value should obey any length limits, and if so, make sure the length of the value is as specified // check if the field's value should obey any length limits, and if so, make sure the length of the value is as specified
if( lengthLimit && lengthLimit.length ){ if( data.lengthLimit && data.lengthLimit.length ){
while( lengthLimit.length ){ while( data.lengthLimit.length ){
if( lengthLimit.pop() == a.length ){ if( data.lengthLimit.pop() == data.value.length ){
alertTxt = message.complete; return true;
return false;
}
} }
} }
if( pattern ){ return this.texts.complete;
}
if( data.pattern ){
var regex, jsRegex; var regex, jsRegex;
switch( pattern ){
switch( data.pattern ){
case 'alphanumeric' : case 'alphanumeric' :
regex = /^[a-zA-Z0-9]+$/i; regex = this.settings.regex.alphanumeric
break; break;
case 'numeric' : case 'numeric' :
regex = /^[0-9]+$/i; regex = this.settings.regex.numeric
break; break;
case 'phone' : case 'phone' :
regex = /^\+?([0-9]|[-|' '])+$/i; regex = this.settings.regex.phone
break; break;
default : default :
regex = pattern; regex = data.pattern;
} }
try{ try{
jsRegex = new RegExp(regex).test(a); jsRegex = new RegExp(regex).test(data.value);
if( a && !jsRegex ) if( data.value && !jsRegex ){
return false; return this.texts.invalid;
}
} }
catch(err){ catch(err){
console.log(err, field, 'regex is invalid'); console.warn(err, field, 'regex is invalid');
return false; return this.texts.invalid;
} }
} }
return true; return true;
}, },
number : function(a){
number : function( field, data ){
var a = data.value;
// if not not a number // if not not a number
if( isNaN(parseFloat(a)) && !isFinite(a) ){ if( isNaN(parseFloat(a)) && !isFinite(a) ){
alertTxt = message.number; return this.texts.number;
return false;
} }
// not enough numbers // not enough numbers
else if( lengthRange && a.length < lengthRange[0] ){ else if( data.lengthRange && a.length < data.lengthRange[0] ){
alertTxt = message.min; return this.texts.short;
return false;
} }
// check if there is max length & field length is greater than the allowed // check if there is max length & field length is greater than the allowed
else if( lengthRange && lengthRange[1] && a.length > lengthRange[1] ){ else if( data.lengthRange && data.lengthRange[1] && a.length > data.lengthRange[1] ){
alertTxt = message.max; return this.texts.long;
return false;
} }
else if( minmax[0] && (a|0) < minmax[0] ){ else if( data.minmax[0] && (a|0) < data.minmax[0] ){
alertTxt = message.number_min; return this.texts.number_min;
return false;
} }
else if( minmax[1] && (a|0) > minmax[1] ){ else if( data.minmax[1] && (a|0) > data.minmax[1] ){
alertTxt = message.number_max; return this.texts.number_max;
return false;
} }
return true; return true;
}, },
// Date is validated in European format (day,month,year) // Date is validated in European format (day,month,year)
date : function(a){ date : function( field, data ){
var day, A = a.split(/[-./]/g), i; var day, A = data.value.split(/[-./]/g), i;
// if there is native HTML5 support: // if there is native HTML5 support:
if( field[0].valueAsNumber ) if( field.valueAsNumber )
return true; return true;
for( i = A.length; i--; ){ for( i = A.length; i--; ){
if( isNaN(parseFloat(a)) && !isFinite(a) ) if( isNaN(parseFloat( data.value )) && !isFinite(data.value) )
return false; return this.texts.date;
} }
try{ try{
day = new Date(A[2], A[1]-1, A[0]); day = new Date(A[2], A[1]-1, A[0]);
if( day.getMonth()+1 == A[1] && day.getDate() == A[0] ) if( day.getMonth()+1 == A[1] && day.getDate() == A[0] )
return day; return true;
return false; return this.texts.date;
} }
catch(er){ catch(er){
console.log('date test: ', err); return this.texts.date;
return false;
} }
}, },
url : function(a){
time : function( field, data ){
var pattern = /^([0-1][0-9]|2[0-3]):[0-5][0-9]$/;
if( pattern.test(data.value) )
return true;
else
return this.texts.time;
},
url : function( field, data ){
// minimalistic URL validation // minimalistic URL validation
function testUrl(url){ if( !this.settings.regex.url.test(data.value) )
return /^(https?:\/\/)?([\w\d\-_]+\.+[A-Za-z]{2,})+\/?/.test( url ); return this.texts.url;
}
if( !testUrl( a ) ){
alertTxt = a ? message.url : message.empty;
return false;
}
return true;
},
hidden : function(a){
if( lengthRange && a.length < lengthRange[0] ){
alertTxt = message.min;
return false;
}
if( pattern ){
var regex;
if( pattern == 'alphanumeric' ){
regex = /^[a-z0-9]+$/i;
if( !regex.test(a) ){
return false;
}
}
}
return true;
},
select : function(a){
if( !tests.hasValue(a) ){
alertTxt = message.select;
return false;
}
return true;
}
};
/* marks invalid fields return true;
},
hidden : function( field, data ){
if( data.lengthRange && data.value.length < data.lengthRange[0] )
return this.texts.short;
if( data.pattern ){
if( data.pattern == 'alphanumeric' && !this.settings.regex.alphanumeric.test(data.value) )
return this.texts.invalid;
}
return true;
},
select : function( field, data ){
return data.value ? true : this.texts.select;
},
checkbox : function( field, data ){
if( field.checked ) return true;
return this.texts.checked;
}
},
/**
* bind events on form elements
* @param {Array/String} types [description]
* @param {Object} formElm [optional - form element, if one is not already defined on the instance]
* @return {[type]} [description]
*/ */
mark = function( field, text ){ events : function( types, formElm ){
if( !text || !field || !field.length ) var that = this;
types = types || this.settings.events;
formElm = formElm || this.DOM.scope;
if( !formElm || !types ) return;
if( types instanceof Array )
types.forEach(bindEventByType);
else if( typeof types == 'string' )
bindEventByType(types)
function bindEventByType( type ){
formElm.addEventListener(type, function(e){
that.checkField(e.target)
}, true);
}
},
/**
* Marks an field as invalid
* @param {DOM Object} field
* @param {String} text
* @return {String} - useless string (should be the DOM node added for warning)
*/
mark : function( field, text ){
if( !text || !field )
return false; return false;
// check if not already marked as a 'bad' record and add the 'alert' object. var that = this;
// check if not already marked as 'bad' and add the 'alert' object.
// if already is marked as 'bad', then make sure the text is set again because i might change depending on validation // if already is marked as 'bad', then make sure the text is set again because i might change depending on validation
var item = field.closest('.' + defaults.classes.item), var item = this.closest(field, '.' + this.settings.classes.item),
alert = item.querySelector('.'+this.settings.classes.alert),
warning; warning;
if( item.hasClass(defaults.classes.bad) ){ if( this.settings.alerts ){
if( defaults.alerts ) if( alert )
item.find('.'+defaults.classes.alert).html(text); alert.innerHTML = text;
else{
warning = '<div class="'+ this.settings.classes.alert +'">' + text + '</div>';
item.insertAdjacentHTML('beforeend', warning);
}
} }
item.classList.remove(this.settings.classes.bad);
else if( defaults.alerts ){
warning = $('<div class="'+ defaults.classes.alert +'">').html( text );
item.append( warning );
}
item.removeClass(defaults.classes.bad);
// a delay so the "alert" could be transitioned via CSS // a delay so the "alert" could be transitioned via CSS
setTimeout(function(){ setTimeout(function(){
item.addClass(defaults.classes.bad); item.classList.add( that.settings.classes.bad );
}, 0); });
};
return warning;
},
/* un-marks invalid fields /* un-marks invalid fields
*/ */
unmark = function( field ){ unmark : function( field ){
if( !field || !field.length ){ var warning;
if( !field ){
console.warn('no "field" argument, null or DOM object not found'); console.warn('no "field" argument, null or DOM object not found');
return false; return false;
} }
field.closest('.' + defaults.classes.item) var fieldWrap = this.closest(field, '.' + this.settings.classes.item);
.removeClass(defaults.classes.bad)
.find('.'+ defaults.classes.alert).remove(); if( fieldWrap ){
}; warning = fieldWrap.querySelector('.'+ this.settings.classes.alert);
fieldWrap.classList.remove(this.settings.classes.bad);
}
if( warning )
warning.parentNode.removeChild(warning);
},
/**
* removes unmarks all fields
* @return {[type]} [description]
*/
reset : function( formElm ){
var fieldsToCheck,
that = this;
formElm = formElm || this.DOM.scope;
fieldsToCheck = this.filterFormElements( formElm.elements );
fieldsToCheck.forEach(function(elm){
that.unmark(elm);
});
},
/**
* Normalize types if needed & return the results of the test (per field)
* @param {String} type [form field type]
* @param {*} value
* @return {Boolean} - validation test result
*/
testByType : function( field, data ){
data = this.extend({}, data); // clone the data
var type = data.type;
function testByType(type, value){
if( type == 'tel' ) if( type == 'tel' )
pattern = pattern || 'phone'; data.pattern = data.pattern || 'phone';
if( !type || type == 'password' || type == 'tel' || type == 'search' || type == 'file' ) if( !type || type == 'password' || type == 'tel' || type == 'search' || type == 'file' )
type = 'text'; type = 'text';
return this.tests[type] ? this.tests[type].call(this, field, data) : true;
},
return tests[type] ? tests[type](value, true) : true; prepareFieldData : function( field ){
} var nodeName = field.nodeName.toLowerCase(),
id = Math.random().toString(36).substr(2,9);
function prepareFieldData(el){ field["_validatorId"] = id;
field = $(el); this.data[id] = {};
field.data( 'valid', true ); // initialize validity of field this.data[id].value = field.value.replace(/^\s+|\s+$/g, ""); // cache the value of the field and trim it
field.data( 'type', field.attr('type') ); // every field starts as 'valid=true' until proven otherwise this.data[id].valid = true; // initialize validity of field
pattern = field.attr('pattern'); this.data[id].type = field.getAttribute('type'); // every field starts as 'valid=true' until proven otherwise
} this.data[id].pattern = field.getAttribute('pattern');
/* Validations per-character keypress
*/
function keypress(e){
prepareFieldData(this);
// String.fromCharCode(e.charCode)
if( e.charCode ){
return testByType( this.type, this.value );
}
}
/* Checks a single form field by it's type and specific (custom) attributes
*/
function checkField(){
// skip testing fields whom their type is not HIDDEN but they are HIDDEN via CSS.
if( this.type !='hidden' && $(this).is(':hidden') )
return true;
prepareFieldData(this);
field.data( 'val', field[0].value.replace(/^\s+|\s+$/g, "") ); // cache the value of the field and trim it
data = field.data();
// Check if there is a specific error message for that field, if not, use the default 'invalid' message
alertTxt = message[field.prop('name')] || message.invalid;
// Special treatment // Special treatment
if( field[0].nodeName.toLowerCase() === "select" ){ if( nodeName === "select" )
data.type = 'select'; this.data[id].type = "select";
}
else if( field[0].nodeName.toLowerCase() === "textarea" ){ else if( nodeName === "textarea" )
data.type = 'text'; this.data[id].type = "text";
}
/* Gather Custom data attributes for specific validation: /* Gather Custom data attributes for specific validation:
*/ */
validateWords = data['validateWords'] || 0; this.data[id].validateWords = field.getAttribute('data-validate-words') || 0;
lengthRange = data['validateLengthRange'] ? (data['validateLengthRange']+'').split(',') : [1]; this.data[id].lengthRange = field.getAttribute('data-validate-length-range') ? (field.getAttribute('data-validate-length-range')+'').split(',') : [1];
lengthLimit = data['validateLength'] ? (data['validateLength']+'').split(',') : false; this.data[id].lengthLimit = field.getAttribute('data-validate-length') ? (field.getAttribute('data-validate-length')+'').split(',') : false;
minmax = data['validateMinmax'] ? (data['validateMinmax']+'').split(',') : ''; // for type 'number', defines the minimum and/or maximum for the value as a number. this.data[id].minmax = field.getAttribute('data-validate-minmax') ? (field.getAttribute('data-validate-minmax')+'').split(',') : false; // for type 'number', defines the minimum and/or maximum for the value as a number.
this.data[id].validateLinked = field.getAttribute('data-validate-linked');
data.valid = tests.hasValue(data.val); return this.data[id];
},
if( field.hasClass('optional') && !data.valid ) /**
data.valid = true; * Find the closeset element, by selector
* @param {Object} el [DOM node]
* @param {String} selector [CSS-valid selector]
* @return {Object} [Found element or null if not found]
*/
closest : function(el, selector){
var matchesFn;
// find vendor prefix
['matches','webkitMatchesSelector','mozMatchesSelector','msMatchesSelector','oMatchesSelector'].some(function(fn){
if( typeof document.body[fn] == 'function' ){
matchesFn = fn;
return true;
}
return false;
})
// for checkboxes var parent;
if( field[0].type === "checkbox" ){
data.valid = field[0].checked; // traverse parents
alertTxt = message.checked; while (el) {
parent = el.parentElement;
if (parent && parent[matchesFn](selector)) {
return parent;
}
el = parent;
} }
return null;
},
/**
* MDN polyfill for Object.assign
*/
extend : function( target, varArgs ){
if( !target )
throw new TypeError('Cannot convert undefined or null to object');
var to = Object(target),
nextKey, nextSource, index;
for( index = 1; index < arguments.length; index++ ){
nextSource = arguments[index];
if( nextSource != null ) // Skip over if undefined or null
for( nextKey in nextSource )
// Avoid bugs when hasOwnProperty is shadowed
if( Object.prototype.hasOwnProperty.call(nextSource, nextKey) )
to[nextKey] = nextSource[nextKey];
}
return to;
},
/* Checks a single form field by it's type and specific (custom) attributes
* {DOM Object} - the field to be checked
* {Boolean} silent - don't mark a field and only return if it passed the validation or not
*/
checkField : function( field, silent ){
// skip testing fields whom their type is not HIDDEN but they are HIDDEN via CSS.
if( field.type !='hidden' && !field.clientWidth )
return { valid:true, error:"" }
field = this.filterFormElements( [field] )[0];
// if field did not pass filtering or is simply not passed
if( !field )
return { valid:true, error:"" }
// this.unmark( field );
var linkedTo,
testResult,
optional = field.className.indexOf('optional') != -1,
data = this.prepareFieldData( field ),
form = this.closest(field, 'form'); // if the field is part of a form, then cache it
// check if field has any value // check if field has any value
else if( data.valid ){
/* Validate the field's value is different than the placeholder attribute (and attribute exists) /* Validate the field's value is different than the placeholder attribute (and attribute exists)
* this is needed when fixing the placeholders for older browsers which does not support them. * this is needed when fixing the placeholders for older browsers which does not support them.
* in this case, make sure the "placeholder" jQuery plugin was even used before proceeding
*/ */
if( tests.sameAsPlaceholder(field) ){
alertTxt = message.empty; // first, check if the field even has any value
testResult = this.tests.hasValue.call(this, data.value);
// if the field has value, check if that value is same as placeholder
if( testResult === true )
testResult = this.tests.sameAsPlaceholder.call(this, field, data );
data.valid = optional || testResult === true;
if( optional && !data.value ){
return { valid:true, error:"" }
}
if( testResult !== true )
data.valid = false; data.valid = false;
// validate by type of field. use 'attr()' is proffered to get the actual value and not what the browsers sees for unsupported types.
if( data.valid ){
testResult = this.testByType(field, data);
data.valid = testResult === true ? true : false;
} }
// if this field is linked to another field (their values should be the same) // if this field is linked to another field (their values should be the same)
if( data.validateLinked ){ if( data.valid && data.validateLinked ){
var linkedTo = data['validateLinked'].indexOf('#') == 0 ? $(data['validateLinked']) : $(':input[name=' + data['validateLinked'] + ']'); if( data['validateLinked'].indexOf('#') == 0 )
data.valid = tests.linked( data.val, linkedTo.val() ); linkedTo = document.body.querySelector(data['validateLinked'])
else if( form.length )
linkedTo = form.querySelector('[name=' + data['validateLinked'] + ']');
else
linkedTo = document.body.querySelector('[name=' + data['validateLinked'] + ']');
testResult = this.tests.linked.call(this, field.value, linkedTo.value, data.type );
data.valid = testResult === true ? true : false;
} }
/* validate by type of field. use 'attr()' is proffered to get the actual value and not what the browsers sees for unsupported types.
if( !silent )
this[data.valid ? "unmark" : "mark"]( field, testResult ); // mark / unmark the field
return {
valid : data.valid,
error : data.valid === true ? "" : testResult
};
},
/**
* Only allow certain form elements which are actual inputs to be validated
* @param {HTMLCollection} form fields Array [description]
* @return {Array} [description]
*/ */
else if( data.valid || data.type == 'select' ) filterFormElements : function( fields ){
data.valid = testByType(data.type, data.val); var i,
fieldsToCheck = [];
for( i = fields.length; i--; ) {
var isAllowedElement = fields[i].nodeName.match(/input|textarea|select/gi),
isRequiredAttirb = fields[i].hasAttribute('required'),
isDisabled = fields[i].hasAttribute('disabled'),
isOptional = fields[i].className.indexOf('optional') != -1;
if( isAllowedElement && (isRequiredAttirb || isOptional) && !isDisabled )
fieldsToCheck.push(fields[i]);
} }
// mark / unmark the field, and set the general 'submit' flag accordingly return fieldsToCheck;
if( data.valid ) },
unmark( field );
else{
mark( field, alertTxt );
submit = false;
}
return data.valid; checkAll : function( formElm ){
} if( !formElm ){
/* vaildates all the REQUIRED fields prior to submiting the form
*/
function checkAll( $form ){
$form = $($form);
if( $form.length == 0 ){
console.warn('element not found'); console.warn('element not found');
return false; return false;
} }
var that = this, var that = this,
submit = true, // save the scope result = {
valid : true, // overall form validation flag
fields : [] // array of objects (per form field)
},
fieldsToCheck = this.filterFormElements( formElm.elements );
// get all the input/textareas/select fields which are required or optional (meaning, they need validation only if they were filled) // get all the input/textareas/select fields which are required or optional (meaning, they need validation only if they were filled)
fieldsToCheck = $form.find(':input').filter('[required=required], .required, .optional').not('[disabled=disabled]');
fieldsToCheck.each(function(){ fieldsToCheck.forEach(function(elm, i){
var fieldData = that.checkField(elm);
// use an AND operation, so if any of the fields returns 'false' then the submitted result will be also FALSE // use an AND operation, so if any of the fields returns 'false' then the submitted result will be also FALSE
submit = submit * checkField.apply(this); result.valid = !!(result.valid * fieldData.valid);
result.fields.push({
field : elm,
error : fieldData.error,
valid : !!fieldData.valid
})
}); });
return !!submit; // casting the variable to make sure it's a boolean return result;
}
} }
return { return FormValidator;
defaults : defaults, }));
checkField : checkField,
keypress : keypress,
checkAll : checkAll,
mark : mark,
unmark : unmark,
message : message,
tests : tests
}
})(jQuery);