Extend HTML5 Form Validation With Custom Rules And Errors – Bouncer.js

Category: Form , Javascript | January 15, 2019
Author: cferdinandi
Views Total: 551
Official Page: Go to website
Last Update: January 15, 2019
License: MIT

Preview:

Extend HTML5 Form Validation With Custom Rules And Errors – Bouncer.js

Description:

The Bouncer.js JavaScript library is created to extend the native HTML5 form validation that enables the customizable form validation on the form fields.

Features:

  • Validate form fields on submit, blur and data change.
  • Custom validation rules.
  • Easy to add your own validators.
  • Custom error messages.
  • Useful API methods and events.

See also:

How to use it:

Download and insert the JavaScript file bouncer.polyfills.js into the web page.

<script src="dist/bouncer.polyfills.js"></script>

Initialize the Bouncer library and we’re ready to go.

var bouncer = new Bouncer('[data-validate]')

Apply validation rules to the form fields as follows:

<form class="validate-me" id="validate-me" data-validate>

  <div>
    <label for="file">Upload any file</label>
    <input name="file" id="file" type="file" data-bouncer-target="#file-error-msg" required>
  </div>

  <div id="file-error-msg"></div>

  <div>
    <label for="color">Color Picker <span class="pattern color">7-Character Hexadecimal (ex. #f7f7f7)</span></label>
    <input type="color" name="color" id="color" pattern="#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})" required>
  </div>

  <div>
    <label for="date">Date <span class="pattern date">YYYY-MM-DD</span></label>
    <input type="date" name="date" id="date" required>
  </div>

  <div>
    <label for="time">Time <span class="pattern time">HH:MM (24-hour time)</span></label>
    <input type="time" name="time" id="time" required>
  </div>

  <div>
    <label for="month">Month <span class="pattern month">YYYY-MM</span></label>
    <input type="month" name="month" id="month" required>
  </div>

  <div>
    <!-- Regex: https://gist.github.com/badsyntax/719800 -->
    <label for="email">Email</label>
    <input type="email" name="email" id="email" data-bouncer-message="The domain portion of the email address is invalid (the portion after the @)." required>
  </div>

  <div>
    <!-- Regex: https://gist.github.com/dperini/729294 -->
    <label for="url">URL</label>
    <input type="url" name="url" id="url" data-bouncer-message="The URL is a missing a TLD (for example, .com)." required>
  </div>

  <div>
    <!-- Regex: https://gist.github.com/dperini/729294 -->
    <label for="urlnotld">URL without TLD allowed</label>
    <input type="url" name="urlnotld" id="urlnotld" pattern="(?:(?:https?|HTTPS?|ftp|FTP):\/\/)(?:\S+(?::\S*)[email protected])?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)(?:\.(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)*)(?::\d{2,5})?(?:[\/?#]\S*)?" required>
  </div>

  <div>
    <label for="number">Number</label>
    <input type="number" name="number" id="number" required>
  </div>

  <div>
    <label for="float">Number (no decimals)</label>
    <input type="number" step="any" name="integer" id="integer" pattern="^(?:[-+]?[0-9]*)$" required>
  </div>

  <div>
    <label for="numberminmax">Number with Min and Max <span class="pattern">Must be between 2 and 7</span></label>
    <input type="number" min="2" max="7" name="numberminmax" id="numberminmax" required>
  </div>

  <div>
    <label for="tel">Tel <span class="pattern">123-456-7890</span></label>
    <input type="text" name="tel" id="tel" pattern="^(?:\d{3}[\-]\d{3}[\-]\d{4})$" required>
  </div>

  <div>
    <label for="password">Password <span class="pattern">At least 1 uppercase character, 1 lowercase character, and 1 number</span></label>
    <input type="password" name="password" id="password" data-bouncer-message="Please choose a password that includes at least 1 uppercase character, 1 lowercase character, and 1 number." pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*" required>
  </div>

  <div>
    <label for="confirm-password">Confirm Password <span class="pattern">must match the field above</span></label>
    <input type="password" name="confirm-password" id="confirm-password" data-bouncer-match="#password" data-bouncer-mismatch-message="Your passwords do not match." required>
  </div>

  <div>
    <label for="textminmax">Text with MinLength and MaxLength <span class="pattern">must be between 3 and 9 characters long</span></label>
    <input type="text" minlength="3" maxlength="9" name="textminmax" id="textminmax" required>
  </div>

  <div>
    <label for="select">Select</label>
    <select name="select" id="select" required>
      <option></option>
      <option>Harry Potter</option>
      <option>Lord of the Rings</option>
      <option>Star Wars</option>
      <option>Start Trek</option>
    </select>
  </div>

  <div>
    <strong>Radio Buttons</strong>
    <label class="label-normal">
      <input type="radio" name="radio" id="radio-1" required>
      Yes
    </label>
    <label class="label-normal">
      <input type="radio" name="radio" id="radio-2" required>
      No
    </label>
  </div>

  <div>
    <strong>Checkboxes</strong>
    <label class="label-normal">
      <input type="checkbox" name="checkbox-1" id="checkbox-1" required>
      Wolverine (must be checked)
    </label>
    <label class="label-normal">
      <input type="checkbox" name="checkbox-2" id="checkbox-2">
      Storm
    </label>
    <label class="label-normal">
      <input type="checkbox" name="checkbox-3" id="checkbox-3">
      Cyclops
    </label>
    <label class="label-normal">
      <input type="checkbox" name="checkbox-4" id="checkbox-4">
      Gambit
    </label>
  </div>

  <input type="submit" class="button" value="Submit">
</form>

Create a custom validator.

var bouncer = new Bouncer('[data-validate]',{
    customValidations: {
      valueMismatch: function (field) {

        // Look for a selector for a field to compare
        // If there isn't one, return false (no error)
        var selector = field.getAttribute('data-bouncer-match');
        if (!selector) return false;

        // Get the field to compare
        var otherField = field.form.querySelector(selector);
        if (!otherField) return false;

        // Compare the two field values
        // We use a negative comparison here because if they do match, the field validates
        // We want to return true for failures, which can be confusing
        return otherField.value !== field.value;

      }
    },
    messages: {
      valueMismatch: function (field) {
        var customMessage = field.getAttribute('data-bouncer-mismatch-message');
        return customMessage ? customMessage : 'Please make sure the fields match.'
      }
    }
})

Customize the error messages.

var bouncer = new Bouncer('[data-validate]',{
    messageAfterField: true,
    messageCustom: 'data-bouncer-message',
    messageTarget: 'data-bouncer-target',
    messages: {
      missingValue: {
        checkbox: 'This field is required.',
        radio: 'Please select a value.',
        select: 'Please select a value.',
        'select-multiple': 'Please select at least one value.',
        default: 'Please fill out this field.'
      },
      patternMismatch: {
        email: 'Please enter a valid email address.',
        url: 'Please enter a URL.',
        number: 'Please enter a number',
        color: 'Please match the following format: #rrggbb',
        date: 'Please use the YYYY-MM-DD format',
        time: 'Please use the 24-hour time format. Ex. 23:00',
        month: 'Please use the YYYY-MM format',
        default: 'Please match the requested format.'
      },
      outOfRange: {
        over: 'Please select a value that is no more than {max}.',
        under: 'Please select a value that is no less than {min}.'
      },
      wrongLength: {
        over: 'Please shorten this text to no more than {maxLength} characters. You are currently using {length} characters.',
        under: 'Please lengthen this text to {minLength} characters or more. You are currently using {length} characters.'
      },
      fallback: 'There was an error with this field.'
    },
})

More configuration options.

var bouncer = new Bouncer('[data-validate]',{

    // Classes & IDs
    fieldClass: 'error',
    errorClass: 'error-message',
    fieldPrefix: 'bouncer-field_',
    errorPrefix: 'bouncer-error_',

    // Patterns
    patterns: {
      email: /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*(\.\w{2,})+$/,
      url: /^(?:(?:https?|HTTPS?|ftp|FTP):\/\/)(?:\S+(?::\S*)[email protected])?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)(?:\.(?:[a-zA-Z\u00a1-\uffff0-9]-*)*[a-zA-Z\u00a1-\uffff0-9]+)*(?:\.(?:[a-zA-Z\u00a1-\uffff]{2,}))\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/,
      number: /^(?:[-+]?[0-9]*[.,]?[0-9]+)$/,
      color: /^#?([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/,
      date: /(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-9])|(?:(?!02)(?:0[1-9]|1[0-2])-(?:30))|(?:(?:0[13578]|1[02])-31))/,
      time: /^(?:(0[0-9]|1[0-9]|2[0-3])(:[0-5][0-9]))$/,
      month: /^(?:(?:19|20)[0-9]{2}-(?:(?:0[1-9]|1[0-2])))$/
    },

    // Custom Validations
    customValidations: {},

    // Form Submission
    disableSubmit: false,

    // Custom Events
    emitEvents: true
    
})

API methods.

// validate a specific form field
bouncer.validate(field);

// validate all form fields
bouncer.validateAll();

// destroy the library
bouncer.destroy();

Event handlers.

document.addEventListener('bouncerShowError', function (event) {
  // when an error is displayed
});

document.addEventListener('bouncerRemoveError', function (event) {
  // when an error is removed
});

document.addEventListener('bouncerFormValid', function (event) {
  // when the form is valid
});

document.addEventListener('bouncerFormInvalid', function (event) {
  // when the form is invalid
}, false);

document.addEventListener('bouncerInitialized', function (event) {
  // when the library is initialized
});

document.addEventListener('bouncerDestroy', function (event) {
  // when the library is destroyed
});

You Might Be Interested In:


Leave a Reply