Fork me

Nod v.1.0.4 A frontend validation jQuery plugin


Writing frontend validation for forms is painfully boring. So I made this in the hopes that it will help make it a little less agonizing for you.

It's designed to

While it isn't strictly Bootstrap dependent, it defaults to the structure that bootstrap uses for its forms. However it should be flexible enough to accomodate most any structure.

Quick introduction

The plugin is made as a jQuery plugin and is activated like this: $("#form").nod( metrics ); The metrics is a list that you build beforehand. It is basically a list of each selector and how you want it validated.

Example:

var metrics = [
  [ '#foo', 'presence', 'Cannot be empty' ],
  [ '#bar', 'min-length:4', 'Must be at least 4 characters long' ]
];
 
$( "#form" ).nod( metrics );

Each "sublist" consists of three parts:

  1. The selector (the validation will be applied to every field that the selector matches)
  2. A string describing what you wish to validate for (see below for documentation)
  3. The error message you wish to display on error

Metrics [ ]

Here is a table with what you can currently validate for:

Name Example
'presence' [ '#foo', 'presence', 'Cannot be empty' ]
'exact:String' [ '#foo', 'exact:bar', 'You have to write "bar"!' ]
'not:String' [ '#foo', 'not:bar', 'Do not write "bar"!' ]
'max-length:Number' [ '#foo', 'max-length:4', 'No longer than 4 characters please' ]
'min-length:Number' [ '#foo', 'min-length:4', 'At least 4 characters please' ]
'exact-length:Number' [ '#foo', 'exact-length:4', 'Must be exactly 4 characters' ]
'between:Number:Number' [ '#foo', 'between:2:4', 'Must be between 2 and 4 characters long' ]
'max-num:Number' [ '#foo', 'max-num:4', 'Type in a number that is at smaller than 5' ]
'min-num:Number' [ '#foo', 'min-num:4', 'Type in a number that is bigger than 3' ]
'between-num:Number:Number' [ '#foo', 'between-num:2:4', 'Type in a number between 2 and 4' ]
'integer' [ '#foo', 'integer', 'Must be a whole number' ]
'float' [ '#foo', 'float', 'Must be a number (decimals are fine)' ]
'same-as:Selector' [ '#email_repeat', 'same-as:#email', 'Your emails do not match' ]
'one-of' (example) [ '#first, #second', 'one-of', 'You must fill out either #first or #second' ]
'email' (read this) [ '#foo', 'email', 'Must be a valid email (RFC 822)' ]
Function [ '#foo', ( function(x) { return x % 2 == 0; } ), 'Must be divisible by two' ]
RegExp [ '#foo', /Hello/, 'String must contain the word "Hello"' ]

If there is something not on the list that you think others would benefit from, then feel free to create a new issue and let me know.

Options { }

You can also pass along an object: $("#form").nod( metrics, options );

Example:

var options = {
  'delay' : 200,
  'submitBtnSelector' : '#submit_btn'
};

Here is a table of everything you can change with the options object.

Name Type Default value Description
delay Number 700 Delay on keyup before it runs a check. Set it to false to disable completely.
disableSubmitBtn Bool true Set to false if you don't want the submit button to be disabled.
helpSpanDisplay String 'help-inline' Set this to help-block if you want error messages to be shown on next line.
groupClass String 'error' The .control-group will get this class if an error is found. Can be set to anything you like, but error, info, warning, or success makes the most sense with bootstrap.
submitBtnSelector String '[type=submit]' Selector to find the submit button. If the form is submitted with a button that is not a member of this selector, then the form will be submitted regardless of errors.
errorPosClasses Array ['.help-inline', '.add-on', button, '.input-append'] When placing the error message, nod will look for these elements (after and above) and place it after these if they exist.
errorClass String 'nod_msg' Used internally. This is the class you want to style if you want any specific styling.
silentSubmit Bool false If set to true, the form will not be submitted the regular way, but instead an event: silentSubmit will be called on the form with the values you'd normally submit. (Read more)
broadcastError Bool false If set to true, nod will trigger an event on the window object. (Read more)
groupSelector String '.control-group' The selector for something surrounding your input elements. Like .control-group in bootstrap forms.

Notes

Radio buttons

These can be a bit tricky to validate, so here's an example.

<div class="control-group">
  <div class="controls">
    <label class="radio">
      <input type="radio" name="a" value="a1" id="bar"> First
    </label>
    <label class="radio">
      <input type="radio" name="a" value="a2"> Second
    </label>
    <label class="radio">
      <input type="radio" name="a" value="a3"> Third
    </label>
  </div>
</div>
<!-- ... -->
<button data-loading-text="loading..." type="submit" class="btn btn-success">Submit form</button>

Pretty standard html. Notice the #bar on line 4 though. To validate for presence on these fields, we don't need the #bar, we just do

var metrics = [
    ['[name=a]', 'presence', 'You must click on at least one radio button']
];
 
$( "#form" ).nod( metrics );

However if we want people to specifically click on a particular radio button, we do (line 2 is still important)

var metrics = [
    ['[name=a]', 'presence', 'You must click on at least one radio button'],
    ['#bar', 'exact:a1', 'You must click on *this* radio button']
];
 
$( "#form" ).nod( metrics );

Conversely we can use the keyword not instead of exact.

Notice name attribute is mandatory on the input fields for all of these.

Ajax checking

Yes, it works. Here's some code:

var getFn = function( value ) {
    $.get('check_email.php', value);
};
 
var metrics = [
    ['#email', getFn, 'This email is already in use']
];
 
$( "#form" ).nod( metrics );

Nod.js will take whatever response it gets from the server and eval it (if possible) to a boolean and use that as an indicator for whether the input is valid. This means that a "truthy" responses like "true", 1, true, "foo" will all return true (the field is valid) and conversely "false", 0, false will return false and be interpreted as if the field is not valid.

Also, if your submit button has data-loading-text, this will be swapped while the check is going on if it was initiated by a click of that button (and swapped back when done, regardless of errors).

Notice This feature is all very beta'ish and kind of hard to test fully. So if you find any errors or things that could be handled more gracefully, then I'd appreciate the feedback.

Email validation

Don't use this. Validating emails should be done backend (by sending an email) and not frontend. I've used the most lax regex for checking emails that I could find (RFC822) so as to err on the side of letting too many emails through rather than rejecting valid emails; but really, you ought not to use frontend email validation at all.

That said, the ones who write the code are not always the ones who get to decide which features to implement, so I've included the feature regardless of what I think about its use. Hope it makes your life a little better.

Silent Submit

if you have set silentSubmit : true, then the form won't submit. Instead you need to listen for the event on the form itself:

var submitFn = function( event, data ) {
  console.log( data );
}
 
$( '#form' ).on( 'silentSubmit', submitFn );

This is used mainly (only?) if you want to submit your form by ajax.

Broadcasting

Say you want to log to your server everytime users make errors in your fields, then set broadcastError : true in your options object and listen for nod_error_fired on the window oject, like this:

var log_error = function( event, data ) {
  console.log( data.el );
  console.log( data.msg );
}
 
$( window ).on( 'nod_error_fired', log_error );

As you can see, you'll get an object with the element (actually the $(el)) and one with the error message.

Downloading

Go to github.com/casperin/nod and fork it. For just a quick plug and play you only need the nod.js or nod.min.js.

Bower: jquery-nod

Contributing

This project is still young and there is plenty of room for improvements, so fork the development branch (we use git flow) and hack away. Nod.js is written in CoffeeScript. Check out the source here. I tried my best to comment the code to make it easy to dive in, but in case you have questions I'd be happy to elaborate. Right now we're (slowly) moving to using Yeoman and Gruntjs, so you will probably want to use that too. It's a bit messy though; but you can test some stuff with grunt test, and concat and minify a version with grunt build. A server is run via grunt server, but (currently) doesn't update on changes to the test files.

If you don't have anything particular you want to contribute with, but just love nod.js so much that you still want to do something (I love you too man), then...

  1. Tests! There is currently not a single test unless you think of CoffeeLint as testing (this is one of the reasons why we're moving to yeoman)
  2. Write examples (see below) and look here for current ones (written in jade).
  3. Clean up gruntfile
  4. Issues...

Examples


<form id="ex1" class="form-horizontal">
  <div class="control-group">
     <label class="control-label">Mandatory field</label>
     <div class="controls">
       <input type="text">
     </div>
   </div>
   <div class="controls">
     <button type="submit" class="btn">Submit</button>
   </div>
 </form>
var metrics = [
  [ 'input', 'presence', 'Cannot be empty' ]
];
$("#ex1").nod( metrics );

<form id="ex2" class="form-horizontal">
  <div class="control-group">
     <label class="control-label">Search for number</label>
     <div class="controls">
       <input type="text" class="search_field" placeholder="type a number and hit enter">
     </div>
   </div>
 </form>
var metrics = [
  [ '.search_field', 'integer', 'Must be a number' ]
];
 
var options = {
  disableSubmitBtn : false
 }
 
$("#ex2").nod( metrics, options );

<form id="ex3" class="form-horizontal">
<div class="control-group">
  <label class="control-label">Type "foo"</label>
  <div class="controls">
    <input type="text" class="ex3a">
  </div>
</div>
<div class="control-group">
  <div class="control-label">
    <label>Select something</label>
  </div>
  <div class="controls">
    <select id="ex3select">
      <option value="">Select something please</option>
      <option value="1">Pick this</option>
      <option value="2">Or this</option>
      <option value="3">But not this</option>
      <option value="4">This is fine though</option>
    </select>
  </div>
</div>
<div class="controls">
  <button type="submit" class="btn">Submit</button>
</div>
var metrics = [
  [ '.ex3a', 'exact:foo', 'I told you to type "foo"!' ],
  [ '#ex3select', 'presence', 'Pick something' ],
  [ '#ex3select', 'not:3', 'I told you not to pick this one!' ],
];
var options = {
  'groupClass' : 'warning',
};
$("#ex3").nod( metrics, options );

Leave at least one number

<form id="ex4" class="form-horizontal">
  <p>Leave at least one number</p>
  <div class="control-group">
    <label class="control-label">Home</label>
    <div class="controls">
      <input type="text" id="ex4a_home">
    </div>
  </div>
  <div class="control-group">
    <label class="control-label">Work</label>
    <div class="controls">
      <input type="text" id="ex4a_work">
    </div>
  </div>
  <div class="control-group">
    <label class="control-label">Mobile</label>
    <div class="controls">
      <input type="text" id="ex4a_mobile">
    </div>
  </div>
  <div class="controls">
    <button type="submit" class="btn">Call me</button>
  </div>
</form>
<script>
  var metrics = [
    [ '#ex4a_home, #ex4a_work, #ex4a_mobile', 'one-of', 'Add at least one number' ]
  ];
  $( '#ex4' ).nod( metrics );
</script>