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** **Critical Bugfixes**
- **Build** - Fixed issue where using a packaged theme without a `site.variables` would cause build to fail - **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** **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 - **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 - **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 - **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: { is: {
bracketedRule: function(rule) {
return (rule.type && rule.type.match(settings.regExp.bracket));
},
valid: function() { valid: function() {
var var
allValid = true allValid = true
@ -285,7 +288,7 @@ $.fn.form = function(parameters) {
keyup: function() { keyup: function() {
keyHeldDown = false; keyHeldDown = false;
}, },
blur: function() { blur: function(event) {
var var
$field = $(this), $field = $(this),
$fieldGroup = $field.closest($group), $fieldGroup = $field.closest($group),
@ -293,13 +296,13 @@ $.fn.form = function(parameters) {
; ;
if( $fieldGroup.hasClass(className.error) ) { if( $fieldGroup.hasClass(className.error) ) {
module.debug('Revalidating field', $field, validationRules); 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') { else if(settings.on == 'blur' || settings.on == 'change') {
module.validate.field( validationRules ); module.validate.field( validationRules );
} }
}, },
change: function() { change: function(event) {
var var
$field = $(this), $field = $(this),
$fieldGroup = $field.closest($group) $fieldGroup = $field.closest($group)
@ -308,7 +311,7 @@ $.fn.form = function(parameters) {
clearTimeout(module.timer); clearTimeout(module.timer);
module.timer = setTimeout(function() { module.timer = setTimeout(function() {
module.debug('Revalidating field', $field, module.get.validation($field)); 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); }, settings.delay);
} }
} }
@ -317,6 +320,18 @@ $.fn.form = function(parameters) {
}, },
get: { 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) { changeEvent: function(type, $input) {
if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) { if(type == 'checkbox' || type == 'radio' || type == 'hidden' || $input.is('select')) {
return 'change'; return 'change';
@ -333,6 +348,18 @@ $.fn.form = function(parameters) {
: 'keyup' : '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() { settings: function() {
var var
firstProperty firstProperty
@ -682,7 +709,7 @@ $.fn.form = function(parameters) {
validate: { validate: {
form: function(event) { form: function(event, ignoreCallbacks) {
var var
values = module.get.values(), values = module.get.values(),
apiRequest apiRequest
@ -698,7 +725,9 @@ $.fn.form = function(parameters) {
if( module.is.valid() ) { if( module.is.valid() ) {
module.debug('Form has no validation errors, submitting'); module.debug('Form has no validation errors, submitting');
module.set.success(); module.set.success();
return settings.onSuccess.call(element, event, values); if(ignoreCallbacks !== true) {
return settings.onSuccess.call(element, event, values);
}
} }
else { else {
module.debug('Form has errors'); module.debug('Form has errors');
@ -710,7 +739,9 @@ $.fn.form = function(parameters) {
if($module.data('moduleApi') !== undefined) { if($module.data('moduleApi') !== undefined) {
event.stopImmediatePropagation(); 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) { $.each(field.rules, function(index, rule) {
if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) { if( module.has.field(field.identifier) && !( module.validate.rule(field, rule) ) ) {
module.debug('Field is invalid', field.identifier, rule.type); module.debug('Field is invalid', field.identifier, rule.type);
fieldErrors.push(rule.prompt); fieldErrors.push(module.get.prompt(rule));
fieldValid = false; fieldValid = false;
} }
}); });
@ -752,42 +783,26 @@ $.fn.form = function(parameters) {
}, },
// takes validation rule and returns whether field passes rule // takes validation rule and returns whether field passes rule
rule: function(field, validation) { rule: function(field, rule) {
var var
$field = module.get.field(field.identifier), $field = module.get.field(field.identifier),
type = validation.type, type = rule.type,
value = $field.val(), value = $field.val(),
bracket = type.match(settings.regExp.bracket), isValid = true,
isValid = true, ancillary = module.get.ancillaryValue(rule),
rule, ruleName = module.get.ruleName(rule),
ancillary, ruleFunction = settings.rules[ruleName]
functionType
; ;
if( !$.isFunction(ruleFunction) ) {
module.error(error.noRule, ruleName);
return;
}
// cast to string avoiding encoding special values // cast to string avoiding encoding special values
value = (value === undefined || value === '' || value === null) value = (value === undefined || value === '' || value === null)
? '' ? ''
: $.trim(value + '') : $.trim(value + '')
; ;
// if bracket notation is used, pass in extra parameters return ruleFunction.call($field, value, ancillary);
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;
} }
}, },
@ -999,6 +1014,36 @@ $.fn.form.settings = {
url : /(https?:\/\/(?:www\.|(?!www))[^\s\.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/i 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 : { selector : {
checkbox : 'input[type="checkbox"], input[type="radio"]', checkbox : 'input[type="checkbox"], input[type="radio"]',
clear : '.clear', clear : '.clear',
@ -1257,6 +1302,32 @@ $.fn.form.settings = {
: false : 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) { creditCard: function(cardNumber, cardTypes) {
var var
cards = { cards = {
@ -1361,29 +1432,14 @@ $.fn.form.settings = {
return (sum % 10 === 0 && sum > 0); return (sum % 10 === 0 && sum > 0);
}, },
// different than another field minCount: function(value, minCount) {
different: function(value, identifier) { if(minCount == 0) {
// use either id or name of field return true;
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 ) { if(minCount == 1) {
matchingValue = $('[name="' + identifier +'[]"]'); return (value !== '');
} }
return (matchingValue !== undefined) return (value.split(',').length >= minCount);
? ( value.toString() !== matchingValue.toString() )
: false
;
}, },
exactCount: function(value, exactCount) { exactCount: function(value, exactCount) {
@ -1396,16 +1452,6 @@ $.fn.form.settings = {
return (value.split(',').length == exactCount); 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) { maxCount: function(value, maxCount) {
if(maxCount == 0) { if(maxCount == 0) {
return false; return false;

|||||||
100:0
Loading…
Cancel
Save