-
Notifications
You must be signed in to change notification settings - Fork 468
Open
Labels
Description
I have several validation rules that should only check if something is likely and warn the user if they fail. The user should still be able to save with those errors.
I solved this by adding a validator that only generates warnings.
$.formUtils.addValidator({
name: 'warn_custom',
validatorFunction: function (val, $el) {
var regexp = new RegExp($el.valAttr('warn-regexp'));
return regexp.test(val);
},
errorMessage: '',
errorMessageKey: 'warnBadCustomVal',
warnOnly : true,
});I then added the ability to store the warnings to the form. It works fine although the code is somewhat hacked.
--- a/public/js/form-validator/jquery.form-validator.js
+++ b/public/js/form-validator/jquery.form-validator.js
@@ -295,16 +295,33 @@
applyInputErrorStyling: function ($input, conf) {
$input
.addClass(conf.errorElementClass)
+ .removeClass(conf.warningElementClass)
.removeClass('valid');
this.getParentContainer($input)
.addClass(conf.inputParentClassOnError)
+ .removeClass(conf.inputParentClassOnWarning)
.removeClass(conf.inputParentClassOnSuccess);
if (conf.borderColorOnError !== '') {
$input.css('border-color', conf.borderColorOnError);
}
},
+ applyInputWarningStyling: function ($input, conf) {
+ $input
+ .removeClass(conf.errorElementClass)
+ .addClass(conf.warningElementClass)
+ .removeClass('valid');
+
+ this.getParentContainer($input)
+ .removeClass(conf.inputParentClassOnError)
+ .addClass(conf.inputParentClassOnWarning)
+ .removeClass(conf.inputParentClassOnSuccess);
+
+ if (conf.borderColorOnError !== '') {
+ $input.css('border-color', conf.borderColorOnError);
+ }
+ },
applyInputSuccessStyling: function($input, conf) {
$input.addClass('valid');
this.getParentContainer($input)
@@ -316,6 +333,7 @@
$input
.removeClass('valid')
.removeClass(conf.errorElementClass)
+ .removeClass(conf.warningElementClass)
.css('border-color', '');
var $parentContainer = dialogs.getParentContainer($input);
@@ -323,6 +341,7 @@
// Reset parent css
$parentContainer
.removeClass(conf.inputParentClassOnError)
+ .removeClass(conf.inputParentClassOnWarning)
.removeClass(conf.inputParentClassOnSuccess);
// Remove possible error message
@@ -333,7 +352,7 @@
}
} else {
$parentContainer
- .find('.' + conf.errorMessageClass)
+ .find('.' + conf.errorMessageClass + ', .' + conf.warningMessageClass)
.remove();
}
@@ -347,7 +366,7 @@
$errorMessagesInTopOfForm.html('');
}
} else {
- $form.find('.' + conf.errorMessageClass + '.alert').remove();
+ $form.find('.' + conf.errorMessageClass + '.alert, .' + conf.warningMessageClass + '.alert').remove();
}
// Remove input css/messages
@@ -355,19 +374,24 @@
dialogs.removeInputStylingAndMessage($(this), conf);
});
},
- setInlineMessage: function ($input, errorMsg, conf) {
-
- this.applyInputErrorStyling($input, conf);
+ setInlineMessage: function ($input, errorMsg, conf, warnOnly) {
+ if (warnOnly) {
+ this.applyInputWarningStyling($input, conf);
+ } else {
+ this.applyInputErrorStyling($input, conf);
+ }
var custom = document.getElementById($input.attr('name') + '_err_msg'),
$messageContainer = false,
setErrorMessage = function ($elem) {
$.formUtils.$win.trigger('validationErrorDisplay', [$input, $elem]);
+ $message.toggleClass(conf.errorMessageClass, !warnOnly);
+ $message.toggleClass(conf.warningMessageClass, warnOnly);
$elem.html(errorMsg);
},
addErrorToMessageContainer = function() {
var $found = false;
- $messageContainer.find('.' + conf.errorMessageClass).each(function () {
+ $messageContainer.find('.' + conf.errorMessageClass + ', .' + conf.warningMessageClass).each(function () {
if (this.inputReferer === $input[0]) {
$found = $(this);
return false;
@@ -380,7 +404,7 @@
setErrorMessage($found);
}
} else if(errorMsg !== '') {
- $message = $('<div class="' + conf.errorMessageClass + ' alert"></div>');
+ $message = $('<div class="' + + ' alert"></div>');
setErrorMessage($message);
$message[0].inputReferer = $input[0];
$messageContainer.prepend($message);
@@ -402,7 +426,7 @@
addErrorToMessageContainer();
} else {
var $parent = this.getParentContainer($input);
- $message = $parent.find('.' + conf.errorMessageClass + '.help-block');
+ $message = $parent.find('.' + conf.errorMessageClass + '.help-block, .' + conf.warningMessageClass + '.help-block');
if ($message.length === 0) {
$message = $('<span></span>').addClass('help-block').addClass(conf.errorMessageClass);
$message.appendTo($parent);
@@ -681,10 +705,12 @@
}
if (result.shouldChangeDisplay) {
- if (result.isValid) {
- $.formUtils.dialogs.applyInputSuccessStyling($elem, conf);
+ if (!result.isValid) {
+ $.formUtils.dialogs.setInlineMessage($elem, result.errorMsg, conf, false);
+ } else if (!result.hasNoWarning) {
+ $.formUtils.dialogs.setInlineMessage($elem, result.warningMsg, conf, true);
} else {
- $.formUtils.dialogs.setInlineMessage($elem, result.errorMsg, conf);
+ $.formUtils.dialogs.applyInputSuccessStyling($elem, conf);
}
}
@@ -879,7 +905,7 @@
$.formUtils.dialogs.setMessageInTopOfForm($form, errorMessages, conf, language);
} else {
$.each(errorInputs, function (i, $input) {
- $.formUtils.dialogs.setInlineMessage($input, $input.attr('current-error'), conf);
+ $.formUtils.dialogs.setInlineMessage($input, $input.attr('current-error'), conf, false);
});
}
if (conf.scrollToTopOnError) {
@@ -1269,6 +1295,7 @@
errorElementClass: 'error', // Class that will be put on elements which value is invalid
borderColorOnError: '#b94a48', // Border color of elements which value is invalid, empty string to not change border color
errorMessageClass: 'form-error', // class name of div containing error messages when validation fails
+ warningMessageClass: 'form-warning', // class name of div containing error messages when validation fails
validationRuleAttribute: 'data-validation', // name of the attribute holding the validation rules
validationErrorMsgAttribute: 'data-validation-error-msg', // define custom err msg inline with element
errorMessagePosition: 'inline', // Can be either "top" or "inline"
@@ -1277,11 +1304,17 @@
messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>',
field: '<li>{msg}</li>'
},
+ warningMessageTemplate: {
+ container: '<div class="{warningMessageClass} alert alert-warning">{messages}</div>',
+ messages: '<strong>{errorTitle}</strong><ul>{fields}</ul>',
+ field: '<li>{msg}</li>'
+ },
scrollToTopOnError: true,
dateFormat: 'yyyy-mm-dd',
addValidClassOnAll: false, // whether or not to apply class="valid" even if the input wasn't validated
decimalSeparator: '.',
inputParentClassOnError: 'has-error', // twitter-bootstrap default class name
+ inputParentClassOnWarning: 'has-warning', // twitter-bootstrap default class name
inputParentClassOnSuccess: 'has-success', // twitter-bootstrap default class name
validateHiddenInputs: false, // whether or not hidden inputs should be validated
inlineErrorMessageCallback: false,
@@ -1399,8 +1432,10 @@
skipBecauseItsEmpty = !value && inputIsOptional,
validationRules = $elem.attr(conf.validationRuleAttribute),
isValid = true,
+ hasNoWarning = true,
errorMsg = '',
- result = {isValid: true, shouldChangeDisplay:true, errorMsg:''};
+ warningMsg = '',
+ result = {isValid: true, hasNoWarning: true, shouldChangeDisplay:true, errorMsg:'', warningMsg:''};
// For input type="number", browsers attempt to parse the entered value into a number.
// If the input is not numeric, browsers handle the situation differently:
@@ -1439,17 +1474,31 @@
$elem = $form.find('[name="' + $elem.attr('name') + '"]:eq(0)');
}
+ var valid = false;
if (eventContext !== 'keyup' || validator.validateOnKeyUp) {
// A validator can prevent itself from getting triggered on keyup
- isValid = validator.validatorFunction(value, $elem, conf, language, $form, eventContext);
+ valid = validator.validatorFunction(value, $elem, conf, language, $form, eventContext);
+ if (validator.warnOnly) {
+ hasNoWarning = hasNoWarning && valid;
+ } else {
+ isValid = isValid && valid;
+ }
}
- if (!isValid) {
+ if (!valid) {
if (conf.validateOnBlur) {
$elem.validateOnKeyUp(language, conf);
}
- errorMsg = $.formUtils.dialogs.resolveErrorMessage($elem, validator, rule, conf, language);
- return false; // break iteration
+ var msg = $.formUtils.dialogs.resolveErrorMessage($elem, validator, rule, conf, language);
+
+ if (validator.warnOnly) {
+ if (!warningMsg) {
+ warningMsg = msg;
+ }
+ } else {
+ errorMsg = msg;
+ return false; // break iteration
+ }
}
} else {
@@ -1473,7 +1522,12 @@
// the input at this time. Most probably some async stuff need to gets finished
// first and then the validator will re-trigger the validation.
result.shouldChangeDisplay = false;
- } else {
+ } else if (hasNoWarning === false) {
+ $elem.trigger('validation', true);
+ result.warningMsg = warningMsg;
+ result.hasNoWarning = false;
+ result.shouldChangeDisplay = true;
+ } else {
$elem.trigger('validation', true);
result.shouldChangeDisplay = true;
}It would be great if a feature like this could be included in the next release