The great thing about open source is that you’re likely to find a project that is as ‘full-featured’ or ‘lightweight’ as your tastes. Happy.js from Henrik Joreteg at &yet aims to be a lightweight form validation plugin for jQuery or Zepto.js that also supports the HTML5 required input attribute.

Setting up the script

To use Happy.js, you’ll need to include three items in your document’s <head>.

jQuery (or Zepto.js)

<script src="jquery.js"></script>

Happy.js itself

<script src="happy.js"></script>

Your JavaScript validation functions either externally referenced or inline, like this example:

<script type="text/javascript" charset="utf-8">
  var happy = {
    USPhone: function (val) {
      console.log('is phone called');
      return /^(?(d{3}))?[- ]?(d{3})[- ]?(d{4})$/.test(val)
    },

    email: function (val) {
      return /^((([a-z]|d|[!#$%&'*+-/=?^_`{|}~]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])+(.([a-z]|d|[!#$%&'*+-/=?^_`{|}~]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])+)*)|((x22)((((x20|x09)*(x0dx0a))?(x20|x09)+)?(([x01-x08x0bx0cx0e-x1fx7f]|x21|[x23-x5b]|[x5d-x7e]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(\([x01-x09x0bx0cx0d-x7f]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))))*(((x20|x09)*(x0dx0a))?(x20|x09)+)?(x22)))@((([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).)+(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).?$/i.test(val);
    },

    minLength: function (val, length) {
      return val.length >= length;
    },

    maxLength: function (val, length) {
      return val.length <= length;
    },

    equal: function (val1, val2) {
      console.log('isEqual called', val1, val2);
      console.log((val1 == val2));
      return (val1 == val2);
    }
  };
</script>

The form markup

With the script in place, you can set up your HTML as usual:

<form id="awesomeForm" action="/lights/camera" method="post">
  <input id="yourName" type="text" name="name" />
  <input id="email" type="text" name="email" />
</form>

… and then add your validation rules with .isHappy:

<script>
  $(document).ready(function () {
    $('#awesomeForm').isHappy({
      fields: {
        // reference the field you're talking about, probably by `id`
        // but you could certainly do $('[name=name]') as well.
        '#yourName': {
          required: true,
          message: 'Might we inquire your name'
        },
        '#email': {
          required: true,
          message: 'How are we to reach you sans email??'
          test: happy.email // this can be *any* function that returns true or false
        }
      }
    });
  }); 
</script>

Validation options determine if a value is required, a message displayed upon failure, and a test function you supply to validate the field value. This function can be anything that returns true or false. On blur and submit events Happy.js will run validations and set an unhappy class on the field and prepend the field with an error message like this one, which you can style with CSS:

<span id=​"textInput1_unhappy" class=​"unhappyMessage">​Please enter an email​</span>

Happy.js also lends itself to Underscore.js integration, with Underscore’s mixin feature:

_.mixin({
  USPhone: function (val) {
    console.log('is phone called');
    return /^(?(d{3}))?[- ]?(d{3})[- ]?(d{4})$/.test(val)
  },

  email: function (val) {
    return /^((([a-z]|d|[!#$%&'*+-/=?^_`{|}~]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])+(.([a-z]|d|[!#$%&'*+-/=?^_`{|}~]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])+)*)|((x22)((((x20|x09)*(x0dx0a))?(x20|x09)+)?(([x01-x08x0bx0cx0e-x1fx7f]|x21|[x23-x5b]|[x5d-x7e]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(\([x01-x09x0bx0cx0d-x7f]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))))*(((x20|x09)*(x0dx0a))?(x20|x09)+)?(x22)))@((([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|d|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).)+(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])|(([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])([a-z]|d|-|.|_|~|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF])*([a-z]|[u00A0-uD7FFuF900-uFDCFuFDF0-uFFEF]))).?$/i.test(val);
  },

  minLength: function (val, length) {
    return val.length >= length;
  },

  maxLength: function (val, length) {
    return val.length <= length;
  },

  equal: function (val1, val2) {
    console.log('isEqual called', val1, val2);
    console.log((val1 == val2));
    return (val1 == val2);
  }
});

With this integration option, set up your validation test to _.email instead of happy.email;

[Source on GitHub] [Comment on Hacker News]


Have comments? Send a tweet to @TheChangelog on Twitter.

Subscribe to The Changelog Weekly – our weekly email covering everything that hits our open source radar.