Documentation adding/changing/styling validation messages with webshims constraint validation
Overriding native validation messages/native validation UI
With HTML5 there are two possible ways to change the validation messages.
- Preventing the native invalid message to appear and replacing it with your own invalid UI (including own validation message or native validation message)
- changing the messages through the setCustomValidity-method - without changing the native UI
A starting point for Preventing the default invalid UI and then replacing it, could look like this:
$('form').bind('invalid', function(e){
//prevent browser from showing native validation message
e.preventDefault();
//implement custom UI and custom message according to the validityState $(e.target).attr('validity')
});
Note: The HTML5 invalid event does not bubble. Webshims lib uses event capturing for listening to the invalid event, so that it can be captured on the form/all ancestor elements
Webshims lib gives you some extensions to make styling validation error message or changing the error-messages really simple.
- firstinvalid (event)
- customValidationMessage (DOM-Property) (Note: to get this new property either
customMessages
oroverrideValidationMessage
has to be set to true before calling$.webshims.polyfill();
) - $.webshims.validityAlert (Helper Object)
- data-errormessage/-x-moz-errormessage content attributes (are automatically used by validityAlert)
Preventing the default and replacing the invalid-bubble with your own message, could look like this:
$('form')
.bind('firstinvalid', function(e){
//show the invalid alert for first invalid element and pass the custom validation message
$.webshims.validityAlert.showFor( e.target, $(e.target).prop('customValidationMessage') );
//prevent browser from showing native validation message
return false;
})
;
Using $.webshims.validityAlert.showFor
will generate the following styleable HTML structure:
<!-- note: span.validity-alert-wrapper is label.validity-alert in old browser, which do not support WAI-ARIA -->
<span class="validity-alert-wrapper" role="alert">
<span class="validity-alert">
<span class="va-arrow"><span class="va-arrow-box"></span></span>
<span class="va-box">Error message of the current field</span>
</span>
</span>
Firefox 4.0 also shows an invalid hint on mouseover, which can't be replaced by this technique. If you want to remove this you can use a title-attribute with an emtpy string or use the x-moz-errormessage to control the error message.
Using instead the setCustomValidity
approach will fully replace the validation message, while the native validation UI stays. Changing the validation message with setCustomValidity, would look like this:
$('input[required]').setCustomValidity('You have to enter something');
The problem with setCustomValidity
is, that setCustomValidity
is a low level API for changing the validityState of an element. This means: The changed validation message is only a side effect, setCustomValidity only works on a single element and also sets the customError-flag to true. The developer has to observe the validityState of an element and has to remove/change the custom validation message dynamically as soon as the message isn't relevant anymore, which can be a real pain in the ass.
//remove customError flag:
$('input[required]').setCustomValidity('');
Due to the fact, that Webshims Lib already had to implement the setCustomValidity approach to do a lot of bugfixing in capable browsers/implementing in uncapable/semi-capable browsers, webshims lib gives you a simple configuration property to dynamically overriding the validationMessage with the customValidationMessage. Simply set the overrideMessages
to true, before calling polyfill
.
//configure custom validation messages before you call polyfill
$.webshims.setOptions('forms', {
overrideMessages: true
});
$.webshims.polyfill();
Note: This site is loaded with overrideMessages = true;
.
Recommendation: Prefer customMessages = true
to overrideMessages = true
(less obtrusiv)
Or a simple rule: If you want to style the validation tooltip use customMessages
and if you want to only change the validationMessage without changing the validation UI use overrideMessages
.
Changing and Adding validation messages
Webshims Lib validation messages are stored @ $.webshims.validityMessages
as an object. The index is the specific language code. Currently there are only really bad validation messages for "en" and "de".
Webshims Lib automatically shows the validation message in the detected language of the browser. If the script doesn't find the right language, it will show the default language which is stored under the key "" (defaults to "en").
You can easily add/change a language by specifying a certain language code.
$.webshims.validityMessages['en'] = {
typeMismatch: {
email: 'changed {%value} is not a legal email address',
url: 'changed {%value} is not a valid web address',
number: 'changed {%value} is not a number!',
date: 'changed {%value} is not a date',
time: 'changed {%value} is not a time',
range: 'changed {%value} is not a number!',
"datetime-local": 'changed {%value} is not a correct date-time format.'
},
rangeUnderflow: 'changed {%value} is too low. The lowest value you can use is {%min}.',
rangeOverflow: 'changed {%value} is too high. The highest value you can use is {%max}.',
stepMismatch: 'changed The value {%value} is not allowed for this form. Only certain values are allowed for this field. {%title}',
tooLong: 'changed The entered text is too large! You used {%valueLen} letters and the limit is {%maxlength}.',
patternMismatch: 'changed {%value} is not in the format this page requires! {%title}',
valueMissing: 'changed You have to specify a value'
};
There are several placeholders, which you can use in your validation message: {%label}
(the text of the label[for]), {%value}
, {%title}
, {%min}
, {%max}
, {%maxlength}
, and {%valueLen}
It is also possible to add more fine grained messages by providing an error message for a specific type.
The following code changes the validation message for a rangeUnderflow in case of the date-type. But will show the defaultMessage
in any other type.
$.webshims.validityMessages['en'] = {
//...
rangeUnderflow = {
date: '{%value} is too early for {%label}. The earliest date you can use is {%min}.',
defaultMessage: '{%value} is too low. The lowest value you can use is {%min}.'
}
//...
};
$.webshims.validityMessages['en'] = {
//...
valueMissing = {
radio: 'Please check one of these options',
defaultMessage: 'You have to specify a value'
}
//...
};
Please let me know, if you enhance the current messages or add new languages.
Create custom error bubbles in all browsers
The following code will explain how to create customized error hints in all browsers. Although it uses some webshims extensions, it shows how you can easily achieve this with HTML5.
//change language in all browsers to en (default is browser language)
//$.webshims.activeLang('en');
//implement customValidationMessage
//$.webshims.setOptions('forms', {
// customMessages: true
//});
//improve custom messages
//$.webshims.validityMessages['en'] = {
// //...
// valueMissing = {
// radio: 'Please check one of these options',
// defaultMessage: 'You have to specify a value'
// }
// //...
//};
//load features
//$.webshims.polyfill();
//wait for DOM-ready and features
$(function(){
$('form')
//the invalid-event is the standard HTML5 validation event,
//which is called on every invalid event, if the user trys to submit an invalid form or
//the author calls checkValidity on an invalid element
.bind('invalid', function(e){
//preventing the default means to cancel the UI-Behavior generated by the browser (so that we can replace it)
e.preventDefault();
})
//custom event, which is fired on the first invalid element
//preventing firstinvalid will prevent all invalid events (but we have already done this)
.bind('firstinvalid', function(e){
//$.webshims.validityAlert is a usefull extension by webshim, which shows an error bubble at a certain element
//simply call $.webshims.validityAlert.showFor(DOM-Element/jQuery-Object/jQuery-Selector);
$.webshims.validityAlert.showFor(e.target, $.attr(e.target, 'customValidationMessage'));
})
;
});
/*load russian localization*/
$.webshims.activeLang("ru");
/*load german localization*/
$.webshims.activeLang("de");
/*load english localization*/
$.webshims.activeLang("en");
Overriding global validation messages on a specific element
You can also set the attribute 'x-moz-errormessage' or 'data-errormessage' to override the global messages.
<label for="name">Name:</label>
<input id="name" required data-errormessage="Please tell us your Name" />
Simple Demo
Now add some extras:
Add valid/invalid Classes on focusout.
//on focusout / blur
$('form').bind('focusout invalid', function(e){
// get target element
var $elem = $(e.target);
//if the element is a candidate for constraint
if($elem.attr('willValidate') && $elem.attr('type') !== 'submit'){
//test wether it is valid and set/remove the classes
if(e.type !== 'invalid' && $elem.is(':valid-element')){
$elem
.closest('.form-element, fieldset')
.addClass('valid')
.removeClass('invalid')
;
} else {
$elem
.closest('.form-element, fieldset')
.addClass('invalid')
.removeClass('valid')
;
}
}
});