Browse Source

Adds default prompts for form validation

pull/3019/head
Jack Lukic 9 years ago
parent
commit
edc9b34928
2 changed files with 119 additions and 69 deletions
  1. 6
      RELEASE-NOTES.md
  2. 182
      src/definitions/behaviors/form.js

6
RELEASE-NOTES.md

@ -5,8 +5,12 @@
**Critical Bugfixes**
- **Build** - Fixed issue where using a packaged theme without a `site.variables` would cause build to fail
**Minor Enhancements**
- **Form Validation** - All form rules now have default validation prompts that will appear if no prompt is specified. These prompts include custom templating.
- **Form Validation** - Form validation bracketed rules can now use simple templating `{value}` to represent bracketed rule in prompt, For example 'Please enter at least {value} characters' with `minLength` rule.
**Bugfixes**
- **Button** -
- **Form Validation** - Validation messages in `error message` group are now correctly removed when invalid field revalidates on blur
- **Table** - Fixed issue where `(x) column segment table` was inheriting accidentally inheriting some grid styles
- **Grid** - Fixed `middle aligned grid` not applying to columns #2959
- **Menu** - Fixed issue where `right menu` was not floating correctly inside a `menu > container` on mobile #2969

182
src/definitions/behaviors/form.js

@ -225,6 +225,9 @@ $.fn.form = function(parameters) {
},
is: {
bracketedRule: function(rule) {
return (rule.type && rule.type.match(settings.regExp.bracket));
},
valid: function() {
var
allValid = true
@ -285,7 +288,7 @@ $.fn.form = function(parameters) {
keyup: function() {
keyHeldDown = false;
},
blur: function() {
blur: function(event) {
var
$field = $(this),
$fieldGroup = $field.closest($group),
@ -293,13 +296,13 @@ $.fn.form = function(parameters) {
;
if( $fieldGroup.hasClass(className.error) ) {
module.debug('Revalidating field', $field, validationRules);
module.validate.field( validationRules );
module.validate.form.call(module, event, true);
}
else if(settings.on == 'blur' || settings.on == 'change') {
module.validate.field( validationRules );
}
},
change: function() {
change: function(event) {
var
$field = $(this),
$fieldGroup = $field.closest($group)
@ -308,7 +311,7 @@ $.fn.form = function(parameters) {
clearTimeout(module.timer);
module.timer = setTimeout(function() {
module.debug('Revalidating field', $field, module.get.validation($field));
module.validate.field( module.get.validation($field) );
module.validate.form.call(module, event, true);
}, settings.delay);
}
}
@ -317,6 +320,18 @@ $.fn.form = function(parameters) {
},
get: {
ancillaryValue: function(rule) {
if(!rule.type || !module.is.bracketedRule(rule)) {
return false;
}
return rule.type.match(settings.regExp.bracket)[1] + '';
},
ruleName: function(rule) {
if( module.is.bracketedRule(rule) ) {
return rule.type.replace(rule.type.match(settings.regExp.bracket)[0], '');
}
return rule.type;
},
changeEvent: function(type, $input) {
if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
return 'change';
@ -333,6 +348,18 @@ $.fn.form = function(parameters) {
: 'keyup'
;
},
prompt: function(rule) {
var
ruleName = module.get.ruleName(rule),
ancillary = module.get.ancillaryValue(rule),
prompt = rule.prompt || settings.prompt[ruleName] || settings.prompt.unspecified
;
prompt = prompt.replace('{value}', ancillary);
if(!rule.prompt) {
module.verbose('Using default validation prompt for type', prompt, ruleName);
}
return prompt;
},
settings: function() {
var
firstProperty
@ -682,7 +709,7 @@ $.fn.form = function(parameters) {
validate: {
form: function(event) {
form: function(event, ignoreCallbacks) {
var
values = module.get.values(),
apiRequest
@ -698,7 +725,9 @@ $.fn.form = function(parameters) {
if( module.is.valid() ) {
module.debug('Form has no validation errors, submitting');
module.set.success();
return settings.onSuccess.call(element, event, values);
if(ignoreCallbacks !== true) {
return settings.onSuccess.call(element, event, values);
}
}
else {
module.debug('Form has errors');
@ -710,7 +739,9 @@ $.fn.form = function(parameters) {
if($module.data('moduleApi') !== undefined) {
event.stopImmediatePropagation();
}
return settings.onFailure.call(element, formErrors, values);
if(ignoreCallbacks !== true) {
return settings.onFailure.call(element, formErrors, values);
}
}
},
@ -733,7 +764,7 @@ $.fn.form = function(parameters) {
$.each(field.rules, function(index, rule) {
if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type);
fieldErrors.push(rule.prompt);
fieldErrors.push(module.get.prompt(rule));
fieldValid = false;
}
});
@ -752,42 +783,26 @@ $.fn.form = function(parameters) {
},
// takes validation rule and returns whether field passes rule
rule: function(field, validation) {
rule: function(field, rule) {
var
$field = module.get.field(field.identifier),
type = validation.type,
value = $field.val(),
bracket = type.match(settings.regExp.bracket),
isValid = true,
rule,
ancillary,
functionType
$field = module.get.field(field.identifier),
type = rule.type,
value = $field.val(),
isValid = true,
ancillary = module.get.ancillaryValue(rule),
ruleName = module.get.ruleName(rule),
ruleFunction = settings.rules[ruleName]
;
if( !$.isFunction(ruleFunction) ) {
module.error(error.noRule, ruleName);
return;
}
// cast to string avoiding encoding special values
value = (value === undefined || value === '' || value === null)
? ''
: $.trim(value + '')
;
// if bracket notation is used, pass in extra parameters
if(bracket) {
ancillary = '' + bracket[1];
functionType = type.replace(bracket[0], '');
rule = settings.rules[functionType];
if( !$.isFunction(rule) ) {
module.error(error.noRule, functionType);
return;
}
isValid = rule.call($field, value, ancillary);
}
else {
rule = settings.rules[type];
if( !$.isFunction(rule) ) {
module.error(error.noRule, type);
return;
}
isValid = rule.call($field, value);
}
return isValid;
return ruleFunction.call($field, value, ancillary);
}
},
@ -999,6 +1014,36 @@ $.fn.form.settings = {
url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i
},
prompt: {
unspecified : 'Please enter a valid value',
empty : 'Please enter a value for field',
checked : 'This field must be checked',
email : 'Please enter a valid e-mail',
url : 'Please enter a valid url',
regExp : 'This field is not formatted correctly',
integer : 'Please enter an integer',
decimal : 'Please enter a decimal',
number : 'Please enter a number',
is : 'This field must be \'{value}\'',
isExactly : 'This field must be exactly \'{value}\'',
not : 'This field cannot be set to \'{value}\'',
notExactly : 'This field cannot be set to exactly \'{value}\'',
contain : 'This field cannot contain \'{value}\'',
containExactly : 'This field cannot contain exactly \'{value}\'',
doesntContain : 'This field must contain \'{value}\'',
doesntContainExactly : 'This field must contain exactly \'{value}\'',
minLength : 'This field must be at least {value} characters',
length : 'This field must be at least {value} characters',
exactLength : 'This field must be exactly {value} characters',
maxLength : 'This field cannot be longer than {value} characters',
match : 'This field must match {value} field',
different : 'Please enter a different value than {value} field',
creditCard : 'Please enter a valid credit card',
minCount : 'You must select at least {value} choices',
exactCount : 'You must select exactly {value} choices',
maxCount : 'You must select {value} or less choices'
},
selector : {
checkbox : 'input[type="checkbox"], input[type="radio"]',
clear : '.clear',
@ -1257,6 +1302,32 @@ $.fn.form.settings = {
: false
;
},
// different than another field
different: function(value, identifier) {
// use either id or name of field
var
$form = $(this),
matchingValue
;
if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
matchingValue = $('[data-validate="'+ identifier +'"]').val();
}
else if($('#' + identifier).length > 0) {
matchingValue = $('#' + identifier).val();
}
else if($('[name="' + identifier +'"]').length > 0) {
matchingValue = $('[name="' + identifier + '"]').val();
}
else if( $('[name="' + identifier +'[]"]').length > 0 ) {
matchingValue = $('[name="' + identifier +'[]"]');
}
return (matchingValue !== undefined)
? ( value.toString() !== matchingValue.toString() )
: false
;
},
creditCard: function(cardNumber, cardTypes) {
var
cards = {
@ -1361,29 +1432,14 @@ $.fn.form.settings = {
return (sum % 10 === 0 && sum > 0);
},
// different than another field
different: function(value, identifier) {
// use either id or name of field
var
$form = $(this),
matchingValue
;
if( $('[data-validate="'+ identifier +'"]').length > 0 ) {
matchingValue = $('[data-validate="'+ identifier +'"]').val();
}
else if($('#' + identifier).length > 0) {
matchingValue = $('#' + identifier).val();
}
else if($('[name="' + identifier +'"]').length > 0) {
matchingValue = $('[name="' + identifier + '"]').val();
minCount: function(value, minCount) {
if(minCount == 0) {
return true;
}
else if( $('[name="' + identifier +'[]"]').length > 0 ) {
matchingValue = $('[name="' + identifier +'[]"]');
if(minCount == 1) {
return (value !== '');
}
return (matchingValue !== undefined)
? ( value.toString() !== matchingValue.toString() )
: false
;
return (value.split(',').length >= minCount);
},
exactCount: function(value, exactCount) {
@ -1396,16 +1452,6 @@ $.fn.form.settings = {
return (value.split(',').length == exactCount);
},
minCount: function(value, minCount) {
if(minCount == 0) {
return true;
}
if(minCount == 1) {
return (value !== '');
}
return (value.split(',').length >= minCount);
},
maxCount: function(value, maxCount) {
if(maxCount == 0) {
return false;

Loading…
Cancel
Save