custom stylable validation bubbles with polyfilled HTML5, CSS3 and ES5 (polyfilled cross-browser + using html5 extensions)
Removes the native error tooltip of HTML5 capable browsers and replaces it with a styleable validation hint. It's a fork of @http://jsfiddle.net/trixta/L4NDp/
by trixta
HTML
<script src="http://afarkas.github.com/webshim/demos/js-webshim/minified/extras/modernizr-custom.js"></script>
<script src="http://afarkas.github.com/webshim/demos/js-webshim/minified/extras/loaders/sssl.js"></script>
<script src="http://afarkas.github.com/webshim/demos/js-webshim/minified/polyfiller.js"></script>
<form class="example">
<div>
<label for="your-name">Name: *</label>
<input type="text" required="required" id="your-name" name="yourName" />
</div>
<div>
<label for="email">email: *</label>
<input type="email" required="required" id="email" name="email" />
</div>
<div>
<label for="name-custom">custom error-message: *</label>
<input required="required" type="text" id="name-custom" name="name-custom" data-errormessage="Please enter something" title="" />
</div>
<div>
<label for="multiple-name-custom">custom error-message: *</label>
<input required="required" type="email" id="multiple-name-custom" name="multiple-name-custom" data-errormessage='{"valueMissing": "Please enter an email address", "typeMismatch": "This is not a valid email address. Please enter a valid one"}' title="" />
</div>
<div>
<input type="submit" />
</div>
</form>
<p><a href="http://afarkas.github.com/webshim/demos/index.html" target="_blank">uses webhsims lib</a></p>
<p><a href="http://jsfiddle.net/trixta/XqPhQ/" target="_top">instant form validation example</a></p>
CSS
body {
font: 100% arial,helvetica,sans-serif;
}
.validity-alert span.va-box {
box-shadow: 2px 2px 5px #E8673B;
-moz-box-shadow: 2px 2px 5px #E8673B;
background: rgb(255, 255, 255);
background: rgba(255, 255, 255, 0.9);
color: #000;
}
.show-error-bubble {
opacity: 1;
visibility: visible;
}
.example {
margin: 10px;
padding: 1px 8px;
background: #fff6c6;
border-radius: 10px;
width: 420px;
}
.example > div:after {
content: " ";
display: block;
clear: both;
}
/* animate all */
.example > div,
.example input[type=text],
.example input[type=email] {
-moz-transition-property: all;
-moz-transition-duration: 1s;
-webkit-transition-property: all;
-webkit-transition-duration: 1s;
-o-transition-property: all;
-o-transition-duration: 1s;
-ms-transition-property: all;
-ms-transition-duration: 1s;
transition-property: all;
transition-duration: 1s;
}
.example > div {
margin: 15px 10px;
padding: 5px 10px;
border-radius: 10px;
background: #ffe268;
box-shadow: 3px 3px 3px #e0c75b;
}
.example > div.invalid {
background: #e8673b;
box-shadow: 3px 3px 3px #e8673b;
}
.example > div.valid {
background: #b0ea74;
box-shadow: 3px 3px 3px #a3d96c;
}
.example input {
box-shadow: none;
}
.example input[type=text],
.example input[type=email] {
float: right;
display: inline-bock;
padding: 0.3em;
height: 1.1em;
width: 180px;
border: 1px solid #d8bf58;
border-radius: 4px;
box-shadow: inset 1px 1px 1px #e0c75b;
background: #fff;
}
.example > div.valid input {
border: 1px solid #9bce67;
box-shadow: inset 1px 1px 1px #87b45a;
}
.example > div.invalid input {
border: 1px solid #a81107;
box-shadow: inset 1px 1px 1px #890e06;
}
.example label {
margin: 0.1em 0 0;
cursor: pointer;
display: inline-block;
vertical-align: middle;
}
.example input[type=submit] {
width: 100%;
text-align: center;
}
JavaScript
(function() {
"use strict";
//load ES5 and HTML5 form features, if not implemented
$.webshims.polyfill('es5 forms');
$(function() {
//objectCreate behaves similiar to Object.create
window.validationUI = $.webshims.objectCreate({
init: function() {
$(document)
.bind('focusout', this.testValidity.bind(this))
//invalid is a simple, non-bubbling event:
//webshims lib sets the useCapture argument in addEventListener to true,
//so that the event is also fired on parent elements
.bind('invalid', this.handleInvalid.bind(this))
//firstinvalid-event is a webshims extension and is triggered only on the first invalid element
.bind('firstinvalid', function(e) {
//$.webshims.validityAlert is an helper object to create simple, styleable error messages
$.webshims.validityAlert.showFor(e.target);
}
);
},
switchClasses: function(elem, removeClass, addClass) {
$(elem).parent().addClass(addClass).removeClass(removeClass);
}
}, {
testValidity: {
value: function(e) {
if (!$(e.target).prop('willValidate') || $(e.target).prop('type') == 'submit') {
return;
}
if ($(e.target).is(':valid')) {
this.switchClasses(e.target, "invalid", "valid");
} else {
this.switchClasses(e.target, "valid", "invalid");
}
}
},
handleInvalid: {
value: function(e) {
this.switchClasses(e.target, "valid", "invalid");
//preventDefault to remove the native browser error UI
...