File "validation.js"
Full Path: /home/londdqdw/public_html/06/wp-content/plugins/the-events-calendar/common/src/resources/js/validation.js
File size: 20.51 KB
MIME-type: text/plain
Charset: utf-8
/**
* Configures this Object in the Global Tribe variable
*
* @since 4.7
*
* @type {Object}
*/
tribe.validation = {};
( function( obj, $, _ ) {
'use strict';
var $document = $( document );
/**
* Object containing all the selectors for Validation
*
* @since 4.7.1
*
* @type {object}
*/
obj.selectors = {
item: '.tribe-validation',
fields: 'input, select, textarea',
submit: '.tribe-validation-submit',
submitButtons: 'input[type="submit"], button[type="submit"]',
error: '.tribe-validation-error',
valid: '.tribe-validation-valid',
notice: '.tribe-notice-validation',
noticeAfter: '.wp-header-end',
noticeFallback: '.wrap > h1',
noticeDismiss: '.notice-dismiss',
};
/**
* Object containing all the conditions for the Fields
*
* @since 4.7
*
* @type {object}
*/
obj.conditions = {
isRequired: function( value ) {
return '' != value; // eslint-disable-line eqeqeq
},
isGreaterThan: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isGreaterThan', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint < condition.value;
},
isGreaterOrEqualTo: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isGreaterOrEqualTo', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint <= condition.value;
},
isLessThan: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isLessThan', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint > condition.value;
},
isLessOrEqualTo: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isLessOrEqualTo', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint >= condition.value;
},
isEqualTo: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isEqualTo', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint == condition.value; // eslint-disable-line eqeqeq
},
isNotEqualTo: function( value, constraint, $field ) {
var condition = obj.parseCondition( 'isNotEqualTo', value, constraint, $field );
// If we failed to parse Condition we don't check
if ( false === condition ) {
return true;
}
return condition.constraint != condition.value; // eslint-disable-line eqeqeq
},
matchRegExp: function( value, constraint, $field ) { // eslint-disable-line no-unused-vars
var exp = new RegExp( constraint, 'g' );
var match = exp.exec( value );
return null !== match;
},
notMatchRegExp: function( value, constraint, $field ) { // eslint-disable-line no-unused-vars
var exp = new RegExp( constraint, 'g' );
var match = exp.exec( value );
return null === match;
}
};
/**
* Object containing types of fields supported
*
* @since 4.7
*
* @type {object}
*/
obj.parseType = {
datepicker: function( value, $constraint, $field ) { // eslint-disable-line no-unused-vars
var formats = [
'yyyy-mm-dd',
'm/d/yyyy',
'mm/dd/yyyy',
'd/m/yyyy',
'dd/mm/yyyy',
'm-d-yyyy',
'mm-dd-yyyy',
'd-m-yyyy',
'dd-mm-yyyy',
'yyyy.mm.dd',
'mm.dd.yyyy',
'dd.mm.yyyy',
];
// Default Format Key
var formatKey = 0;
if ( $constraint.length && $constraint.attr( 'data-datepicker_format' ) ) {
formatKey = $constraint.attr( 'data-datepicker_format' );
} else if ( _.isString( formats[ $constraint ] ) ) {
formatKey = formats[ $constraint ];
} else if ( $constraint.parents( '[data-datepicker_format]' ).length ) {
formatKey = $constraint
.parents( '[data-datepicker_format]' )
.eq( 0 )
.data( 'datepicker_format' );
}
if ( 'undefined' === typeof formats[ formatKey ] || ! formats[ formatKey ] ) {
formatKey = 0;
}
var format = formats[ formatKey ].toUpperCase();
value = moment( value, format ).format( 'X' );
return value;
},
default: function( value, $constraint, $field ) { // eslint-disable-line no-unused-vars
if ( $.isNumeric( value ) ) {
value = parseFloat( value, 10 );
}
return value;
}
};
/**
* Parses the Condition for all the types of conditional and returns a
* better state of Value and Contraint based on the rules for each
*
* @since 4.7
*
* @type {function}
*
* @return {object}
*/
obj.parseCondition = function( conditional, value, constraint, $field ) {
var type = $field.data( 'validationType' );
var $constraint = null;
var condition = { value: value, constraint: constraint };
// When we don't have type we assume default
if ( ! type && ! _.isFunction( obj.parseType[ type ] ) ) {
type = 'default';
}
// If it's not Numeric we treat it like a Selector
if ( ! $.isNumeric( constraint ) ) {
$constraint = $( constraint );
// Check if we got a valid selector before checking Disabled
if ( ! $constraint.length ) {
// Throws a warning so it's easy to spot on development and support
console.warn( 'Tribe Validation:', 'Invalid selector for', $field, constraint );
return false;
}
$constraint = $constraint.not( ':disabled' );
// Verify only for active fields
if ( ! $constraint.length ) {
return false;
}
constraint = $constraint.val();
}
// Applies the type of validation
condition.constraint = obj.parseType[ type ]( constraint, $constraint, $field );
condition.value = obj.parseType[ type ]( value, $constraint, $field );
return condition;
};
/**
* Object containing all the constraints for the Fields
*
* @since 4.7
*
* @type {object}
*/
obj.constraints = {
isRequired: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// Verify by Data value
value = $field.data( 'required' ) || value;
value = $field.data( 'validationRequired' ) || value;
value = $field.data( 'validationIsRequired' ) || value;
// Verify by Attributes
value = $field.is( '[required]' ) || value;
value = $field.is( '[data-required]' ) || value;
value = $field.is( '[data-validation-required]' ) || value;
value = $field.is( '[data-validation-is-required]' ) || value;
return value;
},
isGreaterThan: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-greater-than]' ) ) {
value = $field.data( 'validationIsGreaterThan' );
}
return value;
},
isGreaterOrEqualTo: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-greater-or-equal-to]' ) ) {
value = $field.data( 'validationIsGreaterOrEqualTo' );
}
return value;
},
isLessThan: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-less-than]' ) ) {
value = $field.data( 'validationIsLessThan' );
}
return value;
},
isLessOrEqualTo: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-less-or-equal-to]' ) ) {
value = $field.data( 'validationIsLessOrEqualTo' );
}
return value;
},
isEqualTo: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-equal-to]' ) ) {
value = $field.data( 'validationIsEqualTo' );
}
return value;
},
isNotEqualTo: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-is-not-equal-to]' ) ) {
value = $field.data( 'validationIsNotEqualTo' );
}
return value;
},
matchRegExp: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-match-regexp]' ) ) {
value = $field.data( 'validationMatchRegexp' );
}
return value;
},
notMatchRegExp: function( $field ) {
// Default to Null to prevent Conflicts
var value = null;
// If we have attribute, fetch the data value
if ( $field.is( '[data-validation-not-match-regexp]' ) ) {
value = $field.data( 'validationNotMatchRegexp' );
}
return value;
},
};
/**
* FN (prototype) method from jQuery
*
* @since 4.7
*
* @type {function}
*/
obj.fn = function() {
return this.each( obj.setup );
};
/**
* Configures a Single Form for validation
*
* @since 4.7
*
* @param {int} i Field Index
* @param {DOM} item DOM element for the item
*
* @type {function}
*/
obj.setup = function( i, item ) {
var $item = $( item );
// First we add the Class for the Form
$item.addClass( obj.selectors.item.className() );
// Make the Submit buttons have the required class for The Click
$item.find( obj.selectors.submitButtons ).addClass( obj.selectors.submit.className() )
// On Form Submit
$item.on( 'submit.tribe', obj.onSubmit );
// Actual Validation
$item.on( 'validation.tribe', obj.onValidation );
// Show the errors for all the fields
$item.on( 'displayErrors.tribe', obj.onDisplayErrors );
// Prevent form normal invalidation to be triggered.
$document.on( 'click.tribe', obj.selectors.submit, obj.onClickSubmitButtons );
// When click on dismiss of the notice for errors
$document.on( 'click.tribe', obj.selectors.noticeDismiss, obj.onClickDismissNotice );
};
/**
* Validates a single Field
*
* @since 4.7
*
* @param {int} index Field Index
* @param {DOM} item DOM element for the field
*
* @return {void}
*/
obj.validate = function( index, field ) {
var $field = $( field );
var isValid = obj.isValid( $field );
// If it's valid we bail
if ( isValid ) {
return;
}
$field.addClass( obj.selectors.error.className() );
$field.one( 'change', obj.onChangeFieldRemoveError );
};
/**
* Validates a single Field
*
* @since 4.7
*
* @param {object} $field jQuery Object for the field
*
* @return {bool}
*/
obj.isValid = function( $field ) {
var constraints = obj.getConstraints( $field );
if ( ! _.isObject( constraints ) ) {
return constraints;
}
// It needs to be valid on all to be valid
var valid = _.every( constraints );
return valid;
};
/**
* Validates if a given Section has Errors
*
* @since 4.7
*
* @param {object} $field jQuery Object for the Section been validated
*
* @return {boolean}
*/
obj.hasErrors = function( $item ) {
var $errors = $item.find( obj.selectors.error ).not( ':disabled' );
return 0 !== $errors.length;
};
/**
* Gets which constrains have Passed.
*
* @since 4.7
*
* @param {object} $field jQuery Object for the field.
*
* @return {object} Constraints that have passed.
*/
obj.getConstraints = function( $field ) {
var isDisabled = $field.is( ':disabled' );
var valid = true;
// Bail if it's a disabled field.
if ( isDisabled ) {
return valid;
}
var constraints = obj.getConstraintsValue( $field );
var value = $field.val();
// When we don't have constrains it's always valid.
if ( _.isEmpty( constraints ) ) {
return valid;
}
// Verifies if we have a valid set of constraints.
constraints = _.mapObject( constraints, function( constraint, key ) {
return obj.conditions[ key ]( value, constraint, $field );
} );
return constraints;
};
/**
* Gets which constraint have valid values.
*
* @since 4.7
*
* @param {object} $field Object with all the values for the constraints of a field.
*
* @return {object} Specific constraint value.
*/
obj.getConstraintsValue = function( $field ) {
var isDisabled = $field.is( ':disabled' );
var constraints = {};
// Bail if it's a disabled field
if ( isDisabled ) {
return constraints;
}
// Set to all constraints
constraints = obj.constraints;
// Fetch the values for each one of these
constraints = _.mapObject( constraints, function( isApplicable ) {
return isApplicable( $field );
} );
// Check which ones of these are not null
constraints = _.pick( constraints, function( value ) {
return null !== value;
} );
return constraints;
};
/**
* Gets which jQuery objects are related to a fields constraints
*
* @since 4.7
*
* @param {object} $field jQuery Object for the fields
*
* @return {object} Constraints for validation.
*/
obj.getConstraintsFields = function( $field ) {
var constraints = obj.getConstraintsValue( $field );
// Fetch the values for each one of these
constraints = _.mapObject( constraints, function( constraint ) {
var $constraint = null;
if ( ! _.isNumber( constraint ) && ! _.isBoolean( constraint ) ) {
$constraint = $( constraint );
}
return $constraint;
} );
// Check which ones of these are not null.
constraints = _.pick( constraints, function( value ) {
return value instanceof jQuery;
} );
// Turn this into an proper array.
constraints = _.values( constraints );
// Add the current field.
constraints.unshift( $field );
// Convert to jQuery collection.
constraints = $( constraints ).map( function() {
return this.get();
} );
return constraints;
};
/**
* Actually does the validation for the Form
*
* @since 4.7
*
* @param {object} event JQuery Event
*
* @return {void}
*/
obj.onValidation = function( event ) { // eslint-disable-line no-unused-vars
var $item = $( this );
var $fields = $item.find( obj.selectors.fields );
// Before Validation remove all Errors
$fields.removeClass( obj.selectors.error.className() );
// Validate all Fields
$fields.each( obj.validate );
var $errors = $item.find( obj.selectors.error ).not( ':disabled' );
// if there are errors we show the message and bail
if ( 0 !== $errors.length ) {
$item.trigger( 'displayErrors.tribe' );
return;
}
// If we got here add the valid class
$item.addClass( obj.selectors.valid.className() );
};
/**
* Fired on `displayErrors` for a validation form
*
* @since 4.7
*
* @param {object} event JQuery Event
*
* @return {void}
*/
obj.onDisplayErrors = function( event ) { // eslint-disable-line no-unused-vars
var $item = $( this );
var $errors = $item.find( obj.selectors.error ).not( ':disabled' );
var $list = $( '<ul>' );
var $dismiss = $( '<span>' ).addClass( obj.selectors.noticeDismiss.className() );
// Tries to fetch if we have a given notice
var $notice = $document.find( obj.selectors.notice );
var $newNotice = $( '<div>' )
.addClass( 'notice notice-error is-dismissible tribe-notice' )
.addClass( obj.selectors.notice.className() )
.append( $dismiss );
// Builds based on the errors found in the form
$errors.each( function( i, field ) {
var $field = $( field );
var message = $field.data( 'validationError' );
if ( _.isObject( message ) ) {
var messages = {};
var failed = obj.getConstraints( $field, false );
// Maps the new Keys with CamelCase
_.each( message, function( value, key ) {
messages[ tribe.utils.camelCase( key ) ] = value;
} );
_.each( failed, function( value, key ) {
// Only add error if this validation failed
if ( value ) {
return;
}
obj.addErrorLine( messages[ key ], $field, $list );
} );
} else {
obj.addErrorLine( message, $field, $list );
}
} );
// Appends the List of errors
$newNotice.append( $list );
// Verify if we need to add to the page or replace the existing
if ( 0 === $notice.length ) {
var $wpHeaderEnd = $document.find( obj.selectors.noticeAfter );
if ( 0 === $wpHeaderEnd.length ) {
$wpHeaderEnd = $document.find( obj.selectors.noticeFallback );
}
$wpHeaderEnd.after( $newNotice );
} else{
$notice.replaceWith( $newNotice );
}
};
/**
* Validates a single Field.
*
* @since 4.7
*
* @param {string} message Message to be Attached.
* @param {object} $field jQuery Object for the field.
* @param {object} $list jQuery Object for list of Errors.
*
* @return {void} No return.
*/
obj.addErrorLine = function( message, $field, $list ) {
var $listItem = $( '<li>' ).text( message );
// Add which field has thrown the error
$listItem.data( 'validationField', $field );
// Add which notice item is related to this error field
$field.data( 'validationNoticeItem', $field );
$list.append( $listItem );
};
/**
* Hooks to the submit and if invalid prevents submit from completing.
*
* @since 4.7
*
* @param {object} event JQuery Event.
*
* @return {void|boolean} When invalid it prevent bubble.
*/
obj.onSubmit = function( event ) {
var $item = $( this );
$item.trigger( 'validation.tribe' );
var isValid = $item.is( obj.selectors.valid );
// When Invalid we prevents submit from completing
if ( ! isValid ) {
event.preventDefault();
return false;
}
};
/**
* Hijack the Browser the Invalidation.
*
* Note that it this weird multi-method is required to go around
* the usage of 'invalid' event, which doesn't bubble up to 'form'
* only happens on the Field, which prevents us to use it on
* the ones that are created by JavaScript Templates.
*
* @since 4.7
*
* @uses obj.onInvalidField
*
* @param {object} event JQuery Event
*
* @return {void} No return.
*/
obj.onClickSubmitButtons = function( event ) { // eslint-disable-line no-unused-vars
var $submit = $( this );
var $item = $submit.parents( obj.selectors.item );
// If we are not inside of the Validation just bail
if ( 0 === $item.length ) {
return;
}
// Triggers our validation also on the click of submit
$item.trigger( 'validation.tribe' );
var $fields = $item.find( obj.selectors.fields );
// Makes sure we don't have any invalid event on any fields.
$fields.off( 'invalid.tribe' );
// Configures one invalid trigger
$fields.one( 'invalid.tribe', obj.onInvalidField );
};
/**
* Add a class to mark fields that are invalid and add an one time
* event for these same fields to remove the class on `change`.
*
* @since 4.7
*
* @uses obj.onChangeFieldRemoveError
*
* @param {Event} event JQuery Event.
*
* @return {boolean} Return false to avoid bubble up.
*/
obj.onInvalidField = function( event ) {
var $field = $( this );
var $item = $field.parents( obj.selectors.item );
// Adds the Class for marking the field with an error
$field.addClass( obj.selectors.error.className() );
// Shows the errors
$item.trigger( 'displayErrors.tribe' );
// Adds the Change event to allow removing the error class
$field.one( 'change', obj.onChangeFieldRemoveError );
event.preventDefault();
return false;
};
/**
* Removes error class on fields after they change
*
* @since 4.7
*
* @param {Event} event JQuery Event.
*
* @return {void} No return.
*/
obj.onChangeFieldRemoveError = function( event ) { // eslint-disable-line no-unused-vars
var $field = $( this );
var $relatedFields = obj.getConstraintsFields( $field );
if ( 0 !== $relatedFields.filter( obj.selectors.error ).length ) {
$relatedFields.removeClass( obj.selectors.error.className() );
}
};
/**
* Removes the Notice.
*
* @since 4.7
*
* @param {Event} event JQuery Event.
*
* @return {void} No return.
*/
obj.onClickDismissNotice = function( event ) { // eslint-disable-line no-unused-vars
var $dismiss = $( this );
var $notice = $dismiss.parents( obj.selectors.notice );
// Deletes the Notice
$notice.remove();
};
/**
* Initializes the Validation for the base items
*
* @since 4.7
*
* @param {Event} event JQuery Event.
*
* @return {void} No return.
*/
obj.onReady = function( event ) { // eslint-disable-line no-unused-vars
$( obj.selectors.item ).validation();
};
/**
* Configures the jQuery Setup of the Validation
*
* @since 4.7
*
* @return {void} No return.
*/
$.fn.validation = obj.fn;
/**
* Attaches ready method to the On Ready of Document
*
* @since 4.7
*/
$( obj.onReady );
}( tribe.validation, jQuery, window.underscore || window._ ) );