devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
339 lines (338 loc) • 11.8 kB
JavaScript
/**
* DevExtreme (ui/validation_engine.js)
* Version: 18.1.3
* Build date: Tue May 15 2018
*
* Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
var Class = require("../core/class"),
extend = require("../core/utils/extend").extend,
inArray = require("../core/utils/array").inArray,
each = require("../core/utils/iterator").each,
EventsMixin = require("../core/events_mixin"),
errors = require("../core/errors"),
commonUtils = require("../core/utils/common"),
typeUtils = require("../core/utils/type"),
numberLocalization = require("../localization/number"),
messageLocalization = require("../localization/message");
var BaseRuleValidator = Class.inherit({
NAME: "base",
defaultMessage: function(value) {
return messageLocalization.getFormatter("validation-" + this.NAME)(value)
},
defaultFormattedMessage: function(value) {
return messageLocalization.getFormatter("validation-" + this.NAME + "-formatted")(value)
},
validate: function(value, rule) {
var valueArray = Array.isArray(value) ? value : [value],
result = true;
if (valueArray.length) {
valueArray.every(function(itemValue) {
result = this._validate(itemValue, rule);
return result
}, this)
} else {
result = this._validate(null, rule)
}
return result
}
});
var RequiredRuleValidator = BaseRuleValidator.inherit({
NAME: "required",
_validate: function(value, rule) {
if (!typeUtils.isDefined(value)) {
return false
}
if (false === value) {
return false
}
value = String(value);
if (rule.trim || !typeUtils.isDefined(rule.trim)) {
value = value.trim()
}
return "" !== value
}
});
var NumericRuleValidator = BaseRuleValidator.inherit({
NAME: "numeric",
_validate: function(value, rule) {
if (!rulesValidators.required.validate(value, {})) {
return true
}
if (rule.useCultureSettings && typeUtils.isString(value)) {
return !isNaN(numberLocalization.parse(value))
} else {
return typeUtils.isNumeric(value)
}
}
});
var RangeRuleValidator = BaseRuleValidator.inherit({
NAME: "range",
_validate: function(value, rule) {
if (!rulesValidators.required.validate(value, {})) {
return true
}
var validNumber = rulesValidators.numeric.validate(value, rule),
validValue = typeUtils.isDefined(value),
number = validNumber ? parseFloat(value) : validValue && value.valueOf(),
min = rule.min,
max = rule.max;
if (!(validNumber || typeUtils.isDate(value)) && !validValue) {
return false
}
if (typeUtils.isDefined(min)) {
if (typeUtils.isDefined(max)) {
return number >= min && number <= max
}
return number >= min
} else {
if (typeUtils.isDefined(max)) {
return number <= max
} else {
throw errors.Error("E0101")
}
}
}
});
var StringLengthRuleValidator = BaseRuleValidator.inherit({
NAME: "stringLength",
_validate: function(value, rule) {
value = typeUtils.isDefined(value) ? String(value) : "";
if (rule.trim || !typeUtils.isDefined(rule.trim)) {
value = value.trim()
}
return rulesValidators.range.validate(value.length, extend({}, rule))
}
});
var CustomRuleValidator = BaseRuleValidator.inherit({
NAME: "custom",
validate: function(value, rule) {
var validator = rule.validator,
dataGetter = validator && typeUtils.isFunction(validator.option) && validator.option("dataGetter"),
data = typeUtils.isFunction(dataGetter) && dataGetter(),
params = {
value: value,
validator: validator,
rule: rule
};
if (data) {
params.data = data
}
return rule.validationCallback(params)
}
});
var CompareRuleValidator = BaseRuleValidator.inherit({
NAME: "compare",
_validate: function(value, rule) {
if (!rule.comparisonTarget) {
throw errors.Error("E0102")
}
extend(rule, {
reevaluate: true
});
var otherValue = rule.comparisonTarget(),
type = rule.comparisonType || "==";
switch (type) {
case "==":
return value == otherValue;
case "!=":
return value != otherValue;
case "===":
return value === otherValue;
case "!==":
return value !== otherValue;
case ">":
return value > otherValue;
case ">=":
return value >= otherValue;
case "<":
return value < otherValue;
case "<=":
return value <= otherValue
}
}
});
var PatternRuleValidator = BaseRuleValidator.inherit({
NAME: "pattern",
_validate: function(value, rule) {
if (!rulesValidators.required.validate(value, {})) {
return true
}
var pattern = rule.pattern;
if (typeUtils.isString(pattern)) {
pattern = new RegExp(pattern)
}
return pattern.test(value)
}
});
var EmailRuleValidator = BaseRuleValidator.inherit({
NAME: "email",
_validate: function(value, rule) {
if (!rulesValidators.required.validate(value, {})) {
return true
}
return rulesValidators.pattern.validate(value, extend({}, rule, {
pattern: /^[\d\w\._\-]+@([\d\w\._\-]+\.)+[\w]+$/i
}))
}
});
var rulesValidators = {
required: new RequiredRuleValidator,
numeric: new NumericRuleValidator,
range: new RangeRuleValidator,
stringLength: new StringLengthRuleValidator,
custom: new CustomRuleValidator,
compare: new CompareRuleValidator,
pattern: new PatternRuleValidator,
email: new EmailRuleValidator
};
var GroupConfig = Class.inherit({
ctor: function(group) {
this.group = group;
this.validators = []
},
validate: function() {
var result = {
isValid: true,
brokenRules: [],
validators: []
};
each(this.validators, function(_, validator) {
var validatorResult = validator.validate();
result.isValid = result.isValid && validatorResult.isValid;
if (validatorResult.brokenRule) {
result.brokenRules.push(validatorResult.brokenRule)
}
result.validators.push(validator)
});
this.fireEvent("validated", [{
validators: result.validators,
brokenRules: result.brokenRules,
isValid: result.isValid
}]);
return result
},
reset: function() {
each(this.validators, function(_, validator) {
validator.reset()
})
}
}).include(EventsMixin);
var ValidationEngine = {
groups: [],
getGroupConfig: function(group) {
var result = commonUtils.grep(this.groups, function(config) {
return config.group === group
});
if (result.length) {
return result[0]
}
},
initGroups: function() {
this.groups = [];
this.addGroup()
},
addGroup: function(group) {
var config = this.getGroupConfig(group);
if (!config) {
config = new GroupConfig(group);
this.groups.push(config)
}
return config
},
removeGroup: function(group) {
var config = this.getGroupConfig(group),
index = inArray(config, this.groups);
if (index > -1) {
this.groups.splice(index, 1)
}
return config
},
_setDefaultMessage: function(rule, validator, name) {
if (!typeUtils.isDefined(rule.message)) {
if (validator.defaultFormattedMessage && typeUtils.isDefined(name)) {
rule.message = validator.defaultFormattedMessage(name)
} else {
rule.message = validator.defaultMessage()
}
}
},
validate: function(value, rules, name) {
var result = {
name: name,
value: value,
brokenRule: null,
isValid: true,
validationRules: rules
},
that = this;
each(rules || [], function(_, rule) {
var ruleValidationResult, ruleValidator = rulesValidators[rule.type];
if (ruleValidator) {
if (typeUtils.isDefined(rule.isValid) && rule.value === value && !rule.reevaluate) {
if (!rule.isValid) {
result.isValid = false;
result.brokenRule = rule;
return false
}
return true
}
rule.value = value;
ruleValidationResult = ruleValidator.validate(value, rule);
rule.isValid = ruleValidationResult;
if (!ruleValidationResult) {
result.isValid = false;
that._setDefaultMessage(rule, ruleValidator, name);
result.brokenRule = rule
}
if (!rule.isValid) {
return false
}
} else {
throw errors.Error("E0100")
}
});
return result
},
registerValidatorInGroup: function(group, validator) {
var groupConfig = ValidationEngine.addGroup(group);
if (inArray(validator, groupConfig.validators) < 0) {
groupConfig.validators.push(validator)
}
},
_shouldRemoveGroup: function(group, validatorsInGroup) {
var isDefaultGroup = void 0 === group,
isValidationGroupInstance = group && "dxValidationGroup" === group.NAME;
return !isDefaultGroup && !isValidationGroupInstance && !validatorsInGroup.length
},
removeRegisteredValidator: function(group, validator) {
var config = ValidationEngine.getGroupConfig(group),
validatorsInGroup = config && config.validators;
var index = inArray(validator, validatorsInGroup);
if (index > -1) {
validatorsInGroup.splice(index, 1);
if (this._shouldRemoveGroup(group, validatorsInGroup)) {
this.removeGroup(group)
}
}
},
validateGroup: function(group) {
var groupConfig = ValidationEngine.getGroupConfig(group);
if (!groupConfig) {
throw errors.Error("E0110")
}
return groupConfig.validate()
},
resetGroup: function(group) {
var groupConfig = ValidationEngine.getGroupConfig(group);
if (!groupConfig) {
throw errors.Error("E0110")
}
return groupConfig.reset()
}
};
ValidationEngine.initGroups();
module.exports = ValidationEngine;
module.exports.default = module.exports;