Skip to Content
Menu

liveValidator()

Real-time validation for form inputs to help prevent errors before submission attempt. Uses Bootstrap validation classes (and also works with Contact Form 7).

JavaScript February 7, 2021

Usage

This function runs automatically, so it is not called manually. Is this incorrect?

Examples

Various validated input elements.

HTML
<form class="nebula-validate">
    <div class="form-group">
        <label class="form-control-label" for="yourname">Your Name</label>
        <input id="yourname" class="form-control form-control-lg nebula-validate-text" type="text" placeholder="Your name" required />
        <small class="form-text text-muted">Basic text validates as long as there is value.</small>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="emailaddress">Email</label>
        <input id="emailaddress" class="form-control form-control-lg nebula-validate-email" type="email" placeholder="Email address" />
        <div class="invalid-feedback hidden">Please check that you've entered a valid email address.</div>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="url">URL</label>
        <input id="url" class="form-control form-control-lg nebula-validate-url" type="url" placeholder="http://" />
        <div class="invalid-feedback hidden">Please verify you have entered a valid URL.</div>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="phonenumber">Phone Number</label>
        <input id="phonenumber" class="form-control form-control-lg nebula-validate-phone" type="tel" placeholder="Phone number" />
        <div class="invalid-feedback hidden">Please verify you have entered a valid phone number.</div>
        <small class="form-text text-muted">Supports variations of country codes, area codes, delimiters, and even letters. Try adding an extension, too!</small>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="birthday">Date of Birth</label>
        <input id="birthday" class="form-control form-control-lg nebula-validate-date" type="text" placeholder="Date of birth" />
        <div class="invalid-feedback hidden">Please verify you have entered a valid date.</div>
        <small class="form-text text-muted">Supports both month day year and day month year formats. Also support written out days (with or without year).<br/>Example shown as text input type, but works well with date input type too.</small>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="birthday">Favorite NFL Team</label>
        <select id="fav-nfl-team" class="form-control form-control-lg nebula-validate-regex" data-valid-regex="eagles">
            <option value="">Select a team...</option>
            <option value="eagles">Philadelphia Eagles</option>
            <option value="cowboys">Dallas Cowboys</option>
            <option value="giants">New York Giants</option>
            <option value="redskins">Washington Redskins</option>
        </select>
        <div class="invalid-feedback hidden">I'm sorry, the team you have selected is terrible.</div>
        <small class="form-text text-muted">Example of simple RegEx validation. With select menus, be sure the first option has <code>value=""</code></small>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="regexexample">Favorite HEX color</label>
        <div class="input-group">
            <div class="input-group-addon">#</div>
            <input id="regexexample" class="form-control form-control-lg nebula-validate-regex" data-valid-regex="^#?([a-f0-9]{6}|[a-f0-9]{3})$" type="text" />
        </div>
        <div class="invalid-feedback hidden">Invalid HEX code.</div>
        <small class="form-text text-muted">Example of more complex RegEx validation.</small>
    </div>

    <div class="form-group">
        <label class="form-control-label">Choose an option:</label>
        <div class="form-check form-check-inline">
            <label class="form-check-label">
                <input type="radio" class="form-check-input nebula-validate-radio" name="example-radio-options" value="option1" required /> <div class="label-options"> I am right-handed</div>
            </label>
        </div>
        <div class="form-check form-check-inline">
            <label class="form-check-label">
                <input type="radio" class="form-check-input nebula-validate-radio" name="example-radio-options" value="option2" required /> <div class="label-options"> I am left-handed</div>
            </label>
        </div>
        <div class="invalid-feedback hidden">Please choose your handedness.</div>
        <small class="form-text text-muted">Nebula validation for radios only appears if inputs are somehow unchecked or use <code>applyValidationClasses()</code> manually.</small>
    </div>

    <div class="form-group">
        <label class="form-control-label">Check all that apply:</label>
        <div class="form-check">
            <label class="form-check-label">
                <input type="checkbox" class="form-check-input nebula-validate-checkbox" name="example-checkbox-apply" value="live-on-earth" required /> <div class="label-options"> My primary residence on planet Earth.</div>
            </label>
        </div>
        <div class="form-check">
            <label class="form-check-label">
                <input type="checkbox" class="form-check-input nebula-validate-checkbox" name="example-checkbox-apply" value="eyes-closed" required /> <div class="label-options"> When my eyes are closed they are usually not also open.</div>
            </label>
        </div>
        <div class="form-check">
            <label class="form-check-label">
                <input type="checkbox" class="form-check-input nebula-validate-checkbox" name="example-checkbox-apply" value="never-used-internet" required /> <div class="label-options"> I have never used the Internet.</div>
            </label>
        </div>
        <div class="invalid-feedback hidden">Certainly at least one of those applies!</div>
        <small class="form-text text-muted">Checkbox validation only triggers after an input within the group becomes unchecked.</small>
    </div>

    <div class="form-group">
        <label class="form-control-label" for="yourname">Message</label>
        <textarea id="yourmessage" class="form-control form-control-lg nebula-validate-textarea" placeholder="Enter your message here..." rows="4"></textarea>
        <div class="invalid-feedback hidden">Your message can not be empty.</div>
        <small class="form-text text-muted">Nebula removes validation when focused on textareas to avoid distractions.</small>
    </div>
</form>

Applying a RegEx validator to a Contact Form 7 input field (Zip Code)

JavaScript
jQuery('input[name=zipcode]').removeClass('nebula-validate-text').addClass('nebula-validate-regex').attr('data-valid-regex', '^\\d{5}((-)?\\d{4})?$'); //Remember to escape your escapes!

Additional Notes

Use the class nebula-validate on the form (or containing element) to enable validation. In Contact Form 7, either wrap the whole thing in a <div> or modify the shortcode with html_class="nebula-validate" as seen here.

Note: This validation is meant for visual assistance only (to improve user experience). It is not intended to do secure validation- please use server-side validation for security purposes! Pre-defined RegEx patterns may not perfectly capture all nuances- this is meant for simple forms.

Text / Select

Use the class nebula-validate-text or nebula-validate-select to validate simple text fields and select menus.

Success if they have any value.

Regular Expressions (RegEx)

Use the class nebula-validate-regex to validate fields using a custom RegEx pattern. This requires an attribute of data-valid-regex to be used on the same input. This validation method can be used on any type of input! Be sure to set the value attribute accordingly on appropriate types (like select, checkbox, radio, etc).

Warning if not matching pattern while typing, danger if not matching and not focused. Success if matching.

RegEx patterns should not include the start or end slashes / or flags (/g,/m,/i, etc).

Note: It is currently not possible to use RegEx on a Contact Form 7 form without using custom JavaScript (due to it needing a data attribute). Remember, if using JavaScript to designate the pattern attribute, you’ll need to escape your escapes (See JS example above)!

Email

Use the class nebula-validate-email to validate email fields.

Warning if not valid email address while typing. Danger if invalid and not focused. Success if valid.

URL

Use the class nebula-validate-url to validate URL fields.

Warning if not valid URL while typing. Danger if invalid and not focused. Success if valid.

Phone Number

Use the class nebula-validate-phone to validate phone number fields.

Warning if not valid phone number while typing. Danger if invalid and not focused. Success if valid.

Date

Use the class nebula-validate-date to validate date fields (this works on both date and text input types). This supports both month, day, year and day, month, year formats (and various delimiters). It also works with written-out dates (with or without years).

Warning if not valid date while typing. Danger if invalid and not focused. Success if valid.

Textarea

Use the class nebula-validate-textarea to validate textareas.

Success if they have any value. Removes validation while typing (to avoid distraction).

Checkbox / Radio

Use the class nebula-validate-checkbox or nebula-validate-radio to validate checkboxes and radio fields.

Validation classes will only be applied after unchecking an input. This means that radio groups may not get validation classes without manual JavaScript.

Submit Button

When the submit button is hovered or focused on, any empty fields that are required will highlight with a red border as a real-time visual indicator for the user. This highlight uses the class nebula-empty-required.

Was this page helpful? Yes No


    A feedback message is required to submit this form.


    Please check that you have entered a valid email address.

    Enter your email address if you would like a response.

    Thank you for your feedback!

    Source File

    Located in /assets/js/modules/forms.js on line 532.

    No Hooks

    This function does not have any filters or actions available. Request one?
    JavaScript
    nebula.liveValidator = function(){
        //CF7 Invalid events
        nebula.dom.document.on('wpcf7invalid', function(e){
            setTimeout(function(){ //This triggers before these classes are added by CF7 so wait for 1ms
                jQuery('#' + e.detail.unitTag).find('.wpcf7-not-valid').each(function(){ //Find invalid fields only within this CF7 form
                    nebula.applyValidationClasses(jQuery(this), 'invalid', true);
                });
            }, 1);
        });
    
        //Standard text inputs and select menus
        nebula.dom.document.on('keyup change blur', '.nebula-validate-text, .nebula-validate-textarea, .nebula-validate-select', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else if ( jQuery(this).val().trim().length ){
                nebula.applyValidationClasses(jQuery(this), 'valid', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', ( e.type !== 'keyup' ));
            }
        });
    
        //RegEx input
        nebula.dom.document.on('keyup change blur', '.nebula-validate-regex', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            let pattern = new RegExp(jQuery(this).attr('data-valid-regex'), 'i');
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else if ( pattern.test(jQuery(this).val()) ){
                nebula.applyValidationClasses(jQuery(this), 'valid', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', ( e.type !== 'keyup' ));
            }
        });
    
        //URL inputs
        nebula.dom.document.on('keyup change blur', '.nebula-validate-url', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else if ( nebula.regex.url.test(jQuery(this).val()) ){
                nebula.applyValidationClasses(jQuery(this), 'valid', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', ( e.type !== 'keyup' ));
            }
        });
    
        //Email address inputs
        nebula.dom.document.on('keyup change blur', '.nebula-validate-email', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else if ( nebula.regex.email.test(jQuery(this).val()) ){
                nebula.applyValidationClasses(jQuery(this), 'valid', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', ( e.type !== 'keyup' ));
            }
        });
    
        //Phone number inputs
        nebula.dom.document.on('keyup change blur', '.nebula-validate-phone', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else if ( nebula.regex.phone.test(jQuery(this).val()) ){
                nebula.applyValidationClasses(jQuery(this), 'valid', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', ( e.type !== 'keyup' ));
            }
        });
    
        //Date inputs
        nebula.dom.document.on('keyup change blur', '.nebula-validate-date', function(e){
            if ( e.type === 'focusout' ){
                jQuery(this).val(jQuery(this).val().trim()); //Trim leading/trailing whitespace on blur
            }
    
            //Used to use day.js to validate the date and check that it was between 1800-2999. Now just check that it is not empty.
    
            if ( jQuery(this).val() === '' ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'valid', ( e.type !== 'keyup' )); //This indicates it is valid as long as it isn't empty
            }
        });
    
        //Checkbox and Radio
        //Note: The CF7 "Privacy Acceptance" checkbox does not accept custom classes, so we must use its ID directly here
        nebula.dom.document.on('change blur', '#cf7-privacy-acceptance, .nebula-validate-checkbox, .nebula-validate-radio', function(e){
            if ( jQuery(this).closest('.form-group, .form-check').find('input:checked').length ){
                nebula.applyValidationClasses(jQuery(this), 'reset', false);
            } else {
                nebula.applyValidationClasses(jQuery(this), 'invalid', true);
            }
        });
    
        //Highlight empty required fields when focusing/hovering on submit button
        nebula.dom.document.on('mouseover focus', 'form [type="submit"], form #submit', function(){ //Must be deferred because Nebula replaces CF7 submit inputs with buttons
            let invalidCount = 0;
    
            //This is a non-essential, cosmetic helper, so escape if any errors occur
            try {
                jQuery(this).closest('form').find('[required], .wpcf7-validates-as-required').each(function(){
                    //Look for checked checkboxes or radio buttons
                    if ( jQuery(this).find('input:checked').length ){
                        return; //Continue
                    }
    
                    //Look for empty fields
                    if ( jQuery(this).val().trim().length === 0 ){ //Sometimes jQuery(this) is null and errors on .trim(), so wrapped the whole thing in a try
                        jQuery(this).addClass('nebula-empty-required');
                        invalidCount++;
                    }
                });
            } catch {
                //Ignore
            }
    
            if ( invalidCount > 0 ){
                let invalidCountText = ( invalidCount === 1 )? ' invalid field remains' : ' invalid fields remain';
                jQuery('form [type="submit"], form #submit').attr('title', invalidCount + invalidCountText);
            }
        });
    
        nebula.dom.document.on('mouseout blur', 'form [type="submit"], form #submit', function(){ //Must be deferred because Nebula replaces CF7 submit inputs with buttons
            jQuery(this).closest('form').find('.nebula-empty-required').removeClass('nebula-empty-required');
            jQuery('form [type="submit"], form #submit').removeAttr('title');
        });
    };
    

    Override

    To override or disable this JavaScript function, simply redeclare it with the exact same function name. Remember: Some functionality is conditionally loaded via dynamic imports, so if your function is not overriding properly, try listening for a DOM event (described below).

    JavaScript

    For non-module import functions:

    nebula.liveValidator = function(){
        //Write your own code here, leave it blank, or return false.
    }


    For dynamically imported module function overrides:

    jQuery(window).on('load', function(){
        nebula.liveValidator = function(){
            //Write your own code here, leave it blank, or return false.
        }
    });


    Custom Nebula DOM events do also exist, so you could also try the following if the Window Load listener does not work:

    jQuery(document).on('nebula_module_loaded', function(module){
        //Note that the module variable is also available to know which module specifically was imported
        if ( typeof nebula.liveValidator === 'function' ){
            nebula.liveValidator = function(){
                //Write your own code here, leave it blank, or return false.
            }
    	}
    });