Native Implementation of Jquery Validation Plugin

Wellidate is a fast, easy-to-use JavaScript form validation library that supports both native HTML5 validation attribute and HTML data attribute.

More features:

  • Auto moves the focus to the invalid form field.
  • Custom error messages and styles.
  • 20+ built-in validation rules (see below).
  • Allows to include/exclude form fields.
  • Allows to display results in a Summary container.

Validation rules included:

  1. accept
  2. date
  3. digits
  4. email
  5. equalto
  6. filesize
  7. greater
  8. integer
  9. length
  10. lower
  11. max
  12. maxlength
  13. min
  14. minlength
  15. number
  16. range
  17. regex
  18. remote
  19. required
  20. step

How to use it:

Download the insert the JavaScript file into the document and we’re ready to go.

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

Apply rules to form fields using HTML5 form validation attributes or HTML data-val-ruleName attributes as follows:

<form>
  <label for="data-name">Name</label>
  <input name="data-name" data-val-required="" data-val-length="" data-val-length-max="10">
   
  <button>Submit</button>
</form>
<!-- OR -->
<form>
  <label for="data-name">Name</label>
  <input name="data-name" required minlength="2" maxlength="10">
   
  <button>Submit</button>
</form>

Initialize the Wellidate on the HTML form and done.

new Wellidate(document.querySelector('form'));

All possible options to customize the form validation. You can pass the following options as an object to the Wellidate method.

new Wellidate(document.querySelector('form'),{

    // moves the focus to the invaild field
    focusInvalid: true,

    // configurable submit handler
    submitHandler: null,

    // moves the focus to the field after clean up
    focusCleanup: false,

    // includes the following form fields
    include: 'input,textarea,select',

    // for displaying results
    summary: {
      container: '[data-valmsg-summary=true]',
      show: function (result) {
        if (this.container) {
          var summary = document.querySelector(this.container);

          if (summary) {
            summary.innerHTML = '';

            if (result.isValid) {
              summary.classList.add('validation-summary-valid');
              summary.classList.remove('validation-summary-errors');
            } else {
              summary.classList.add('validation-summary-errors');
              summary.classList.remove('validation-summary-valid');

              var list = document.createElement('ul');

              result.invalid.forEach(function (invalid) {
                var item = document.createElement('li');

                item.innerHTML = invalid.message;

                list.appendChild(item);
              });

              summary.appendChild(list);
            }
          }
        }
      },
      reset: function () {
        this.show({
          isValid: true,
          invalid: []
        });
      }
    },

    // default classes
    classes: {
      inputPending: 'input-validation-pending',
      inputError: 'input-validation-error',
      inputValid: 'input-validation-valid',
      fieldPending: 'input-validation-pending',
      fieldError: 'field-validation-error',
      fieldValid: 'field-validation-valid',
      wasValidated: 'was-validated'
    },

    // excludes following form fields
    excludes: [
      'input[type=button]',
      'input[type=submit]',
      'input[type=image]',
      'input[type=reset]',
      ':disabled'
    ],

    // basic rules
    rule: {
      trim: true,
      message: 'This field is not valid.',
      isValid: function () {
          return false;
      },
      isEnabled: function () {
          return true;
      },
      formatMessage: function () {
        return this.message;
      },
      normalizeValue: function (element) {
        element = element || this.element;
        var value = element.value;

        if (element.tagName == 'SELECT' && element.multiple) {
          return [].filter.call(element.options, function (option) {
            return option.selected;
          }).length;
        } else if (element.type == 'radio') {
          if (element.name) {
            var name = this.wellidate.escapeAttribute(element.name);
            var checked = document.querySelector('input[name="' + name + '"]:checked');

            value = checked ? checked.value : '';
          } else {
            value = element.checked ? value : '';
          }
        } else if (element.type == 'file') {
          if (value.lastIndexOf('\\') >= 0) {
            value = value.substring(value.lastIndexOf('\\') + 1);
          } else if (value.lastIndexOf('/') >= 0) {
            value = value.substring(value.lastIndexOf('/') + 1);
          }
        }

        return this.trim ? value.trim() : value;
      }
    }

});

Default validation rules. Override the following validation rules as per your needs.

new Wellidate(document.querySelector('form'),{
    rules: {
      required: {
          message: 'This field is required.',
          isValid: function () {
              return Boolean(this.normalizeValue());
          }
      },
      equalto: {
          message: 'Please enter the same value again.',
          isValid: function () {
              var other = document.getElementById(this.other);

              return other && this.normalizeValue() == this.normalizeValue(other);
          }
      },
      length: {
          message: 'Please enter a value between {0} and {1} characters long.',
          isValid: function () {
              var length = this;
              var value = length.normalizeValue();

              return (length.min == null || length.min <= value.length) && (value.length <= length.max || length.max == null);
          },
          formatMessage: function () {
              var length = this;

              if (length.min != null && length.max == null && !length.isDataMessage) {
                  return Wellidate.prototype.rules.minlength.message.replace('{0}', length.min);
              } else if (length.min == null && length.max != null && !length.isDataMessage) {
                  return Wellidate.prototype.rules.maxlength.message.replace('{0}', length.max);
              }

              return length.message.replace('{0}', length.min).replace('{1}', length.max);
          }
      },
      minlength: {
          message: 'Please enter at least {0} characters.',
          isValid: function () {
              return this.min == null || !parseFloat(this.min) <= this.normalizeValue().length;
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.min);
          }
      },
      maxlength: {
          message: 'Please enter no more than {0} characters.',
          isValid: function () {
              return this.normalizeValue().length <= this.max || !parseFloat(this.max);
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.max);
          }
      },
      email: {
          message: 'Please enter a valid email address.',
          isValid: function () {
              return /^$|^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(this.normalizeValue());
          }
      },
      integer: {
          message: 'Please enter a valid integer value.',
          isValid: function () {
              return /^$|^[+-]?\d+$/.test(this.normalizeValue());
          }
      },
      number: {
          message: 'Please enter a valid number.',
          scaleMessage: 'Please enter a value with no more than {0} fractional digits',
          precisionMessage: 'Please enter a value using no more than {0} significant digits',
          isValid: function () {
              return /^$|^[+-]?(\d+|\d{1,3}(,\d{3})+)?(\.\d+)?$/.test(this.normalizeValue());
          }
      },
      digits: {
          message: 'Please enter only digits.',
          isValid: function () {
              return /^\d*$/.test(this.normalizeValue());
          }
      },
      date: {
          message: 'Please enter a valid date.',
          isValid: function () {
              return /^$|^\d{4}-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$/.test(this.normalizeValue());
          }
      },
      range: {
          message: 'Please enter a value between {0} and {1}.',
          isValid: function () {
              var range = this;
              var value = range.normalizeValue2();

              return !value || (range.min == null || range.min <= parseFloat(value)) && (parseFloat(value) <= range.max || range.max == null);
          },
          formatMessage: function () {
              var range = this;

              if (range.min != null && range.max == null && !range.isDataMessage) {
                  return Wellidate.prototype.rules.min.message.replace('{0}', range.min);
              } else if (range.min == null && range.max != null && !range.isDataMessage) {
                  return Wellidate.prototype.rules.max.message.replace('{0}', range.max);
              }

              return range.message.replace('{0}', range.min).replace('{1}', range.max);
          }
      },
      min: {
          message: 'Please enter a value greater than or equal to {0}.',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !parseFloat(this.value) || this.value <= parseFloat(value);
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.value);
          }
      },
      max: {
          message: 'Please enter a value less than or equal to {0}.',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !parseFloat(this.value) || parseFloat(value) <= this.value;
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.value);
          }
      },
      greater: {
          message: 'Please enter a value greater than {0}.',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !parseFloat(this.than) || this.than < parseFloat(value);
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.than);
          }
      },
      lower: {
          message: 'Please enter a value lower than {0}.',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !parseFloat(this.than) || parseFloat(value) < this.than;
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.than);
          }
      },
      step: {
          message: 'Please enter a multiple of {0}.',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !parseFloat(this.value) || parseFloat(value) % this.value == 0;
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.value);
          }
      },
      filesize: {
          page: 1024,
          message: 'File size should not exceed {0} MB.',
          isValid: function () {
              var size = [].reduce.call(this.element.files, function (total, file) {
                  return total + file.size;
              }, 0);

              return size <= this.max || this.max == null;
          },
          formatMessage: function () {
              var filesize = this;
              var mb = (filesize.max / filesize.page / filesize.page).toFixed(2);

              return filesize.message.replace('{0}', mb.replace(/[.|0]*$/, ''));
          }
      },
      accept: {
          message: 'Please select files in correct format.',
          isValid: function () {
              var filter = this.types.split(',').map(function (type) {
                  return type.trim();
              });

              var correct = [].filter.call(this.element.files, function (file) {
                  var extension = file.name.split('.').pop();

                  for (var i = 0; i < filter.length; i++) {
                      if (filter[i].indexOf('.') == 0) {
                          if (file.name != extension && '.' + extension == filter[i]) {
                              return true;
                          }
                      } else if (/\/\*$/.test(filter[i])) {
                          if (file.type.indexOf(filter[i].replace(/\*$/, '')) == 0) {
                              return true;
                          }
                      } else if (file.type == filter[i]) {
                          return true;
                      }
                  }

                  return !filter.length;
              });

              return this.element.files.length == correct.length;
          }
      },
      regex: {
          message: 'Please enter value in a valid format. {0}',
          isValid: function () {
              var value = this.normalizeValue();

              return !value || !this.pattern || new RegExp(this.pattern).test(value);
          },
          formatMessage: function () {
              return this.message.replace('{0}', this.title || '');
          }
      },
      remote: {
          type: 'get',
          message: 'Please fix this field.',
          isValid: function (validatable) {
              var remote = this;

              if (remote.request && remote.request.readyState != 4) {
                  remote.request.abort();
              }

              clearTimeout(remote.start);
              remote.start = setTimeout(function () {
                  if (validatable.isValid) {
                      remote.request = new XMLHttpRequest();
                      remote.request.open(remote.type, remote.buildUrl(), true);
                      remote.request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

                      remote.request.onload = function () {
                          if (validatable.isValid && 200 <= this.status && this.status < 400) {
                              remote.apply(validatable, this.responseText);
                          }
                      };

                      remote.prepare(validatable);

                      remote.request.send();

                      validatable.pending();
                  }
              }, 1);

              return true;
          },
          buildUrl: function () {
              var remote = this;
              var url = remote.url.split('?', 2)[0];
              var fields = (remote.additionalFields || '').split(',').filter(Boolean);
              var query = (remote.url.split('?', 2)[1] || '').split('&').filter(Boolean);

              for (var i = 0; i < fields.length; i++) {
                  var element = document.querySelector(fields[i]);
                  var value = remote.normalizeValue(element) || '';

                  query.push(encodeURIComponent(element.name) + "=" + encodeURIComponent(value));
              }

              query.push(encodeURIComponent(remote.element.name) + "=" + encodeURIComponent(remote.normalizeValue() || ''));

              return url + '?' + query.join('&');
          },
          prepare: function () {
          },
          apply: function (validatable, response) {
              var result = JSON.parse(response);

              if (result.isValid === false) {
                  validatable.error('remote', result.message);
              } else {
                  validatable.success(result.message);
              }
          }
      }
    }
});

API methods.

var instance = new Wellidate(document.querySelector('form'));

// checks if is valid
instance.isValid(fieldName);

// Validates all or selected fields
instance.form();

// Validates the form and returns the validation results for each field
instance.validate();

// rebuilds the instnace
instance.rebuild();

// applies rules to fields
instance.apply({
  '#name': {
    error: 'Enter a unique name'
  },
  // ...
});

// resets the form
instance.reset();

Download Details:

Author: NonFactors

Demo: https://nonfactors.github.io/Wellidate/

Source Code: https://github.com/NonFactors/Wellidate

#javascript

Native Implementation of Jquery Validation Plugin
1.85 GEEK