Simple form validation I would really like to hear how I can improve my form validator. Next, I want to refactor it into OO and learn a testing framework like Jasmine.

Some things I know I could improve:


Don't make it tied to the DOM as much (using parent().parent(), for ex.).
Combined validations can't be used. For example, using isBlank and isInteger will not validate properly because if isInteger fails, it throws an error and isBlank passes and clears all errors.
Make a config object to update with custom error messages.
Possibly make a jQuery plugin so passing the object to validate is easier.


Github repo

  jQuery -&gt; # on Document ready

    errorCount = null

    valEl = $('.validate')  # cache .validate elements
    submitBtn = valEl.parent().parent().find('input[type=submit]')

    valEl.on "blur", -&gt;
      input = $(this)
      validate(input)

    validate = (input) -&gt;
      inputVal = input.val()
      inputLen = inputVal.length
      validations = input.data()         #cache data-xxx tags

      if validations.notblank is on
        if inputLen &lt;= 0
          throwError("This field can't be blank", input)
        else
          removeError(input)

      if validations.minchars &gt; 0
        if inputLen &lt; validations.minchars
          throwError("You need at least 5 chars", input)
        else
          removeError(input)

      if validations.isinteger is on
        isInteger = /^\d+$/
        if isInteger.test(inputVal) is false
          throwError("Must be a whole number", input)
        else
          removeError(input)

    throwError = (message, input) -&gt;
      if !input.hasClass('has-error')
        errorCount += 1
        input.addClass "has-error"
        input.nextAll('.errorContainer').append(message)

    removeError = (input) -&gt;
      if input.hasClass('has-error')
        errorCount -= 1
        input.removeClass("has-error")
        input.nextAll('.errorContainer').empty()

    submitBtn.on "click", (e) -&gt;
      e.preventDefault()
      if errorCount is 0
        valEl.parent().parent().submit()
You could break out your validation functions into a separate object, like so:

validators =
  isinteger: (input) -&gt;
    # check that value is an int

  notblank: (input) -&gt;
    # check that value is present


These functions could return a simple boolean, or they could return an error message if validation fails and null if it passes.

The point is that you keep the functions separate, so they're easier to manage and customize. But it also means that you can give your inputs data attributes like data-validator which simply is the name of the validation method to use. So you can say, for example

method = $(input).data "validator"
result = validators[method]?(input)


With a little string-splitting, you could make the field plural, like data-validators="isinteger, notblank", and check each.

You could also make the error-throwing into an event you can listen for elsewhere. Then you avoid having your error presentation mixed up with your validations, and you don't have to rely on a predefined .errorContainer element. For instance:

throwError = (message, input) -&gt;
  $(input).trigger 'validation:error', message

# ... elsewhere ...

$(document).on 'validation:error', 'input', (event) -&gt;
  # handle error event




Other stuff I noticed:


Don't bind to the submit button's click event! Forms can also be submitted by simply pressing enter/return, without ever clicking the submit button. Instead, bind the form element's submit event which is fired regardless of how the form is submitted, and use preventDefault() to stop the submission if necessary.
Your notblank logic won't complain if the user just enters some space characters. In most cases the field should probably be considered blank, if it only contains whitespace. So use $.trim() on the value first, to trim off leading and trailing whitespace. 
HTML5 has a required attribute you can add to inputs - no need to have your own syntax for say an input should be notblank. Check for the required attribute instead (if $(input).attr('required') ...). It makes the HTML more semantically correct.




I don't know if you already have solutions for the specific things you mention, but here are my ideas:


You can use .closest("form") to find the form element instead of parent().parent()
If you store all validation failures in an array, you just need to check the array's length, to see if the were any errors. Multiple validations won't override each other, and you don't need errorCount