Skip to content

Instantly share code, notes, and snippets.

@arniebradfo
Last active June 7, 2016 21:53
Show Gist options
  • Save arniebradfo/1d59554b8e2db28d1b3effc048be06cc to your computer and use it in GitHub Desktop.
Save arniebradfo/1d59554b8e2db28d1b3effc048be06cc to your computer and use it in GitHub Desktop.
Safari Form Validation Pollyfill - halts form submission if it has invalid required fields and adds tool tip like other browsers do
/**
* Safari Form Validation Pollyfill
* halts form submission if it has invalid required fields
* and adds tool tip emulating other browser's native behavior
* Tooltip is styled to match safari
*
* @requires modernizer.js
* @link https://gist.github.com/arniebradfo/1d59554b8e2db28d1b3effc048be06cc/
* @author James Bradford
* @link http://arniebradfo.com
*/
(function (document, window, Modernizr) {
var style = document.getElementById('safariFormValidationWarningElementCSS');
if (style == null) {
style = document.createElement('style'); // Create the <style> tag
style.setAttribute('id', 'safariFormValidationWarningElementCSS');
var styles = '\
/* styles added to this sheet with js */\
@keyframes safariFormValidationWarningElementEnter {\
from { transform: translateY(50%) translateZ(0); opacity: 0; }\
to { transform: translateY(0) translateZ(0); opacity: 1; }\
}\
.safariFormValidationWarningElement{\
position: fixed;\
background-color: white;\
z-index: 9999;\
padding: 7px 6px 4px;\
border-radius: 5px;\
box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.55), 0px 0px 4px 0px rgba(0,0,0,0.4);\
wrap: nowrap;\
color: #666;\
font-weight: 700;\
text-transform: uppercase;\
font-size: 12px;\
line-height: 1em;\
font-style: normal;\
font-family: Helvetica Nue, Helvetica, sans-serif;\
transition: transform opacity;\
animation: safariFormValidationWarningElementEnter 300ms ease-out;\
}\
.safariFormValidationWarningElement:before{\
content: "";\
bottom: 100%;\
left: 10px;\
height: 3px;\
position:absolute;\
height: 5px;\
width: 10px;\
border-bottom: 5px solid orange;\
border-right: 5px solid transparent;\
border-left: 5px solid transparent;\
background-color: transparent;\
}\
.safariFormValidationWarningElement:after{\
content:"";\
right: 0;\
left: 0;\
top: 0;\
height: 3px;\
position: absolute;\
background-color: orange;\
border-top-right-radius: 5px;\
border-top-left-radius: 5px;\
}\
';
style.appendChild(document.createTextNode(styles));
document.head.appendChild(style);
}
var removeWarningElements = function () {
var elements = document.getElementsByClassName('safariFormValidationWarningElement');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
element.remove();
}
document.removeEventListener('click', removeWarningElements, false);
document.removeEventListener('keydown', removeWarningElements, false);
document.removeEventListener('touchstart', removeWarningElements, false);
document.removeEventListener('wheel', removeWarningElements, false);
};
var validateForm = function (event) {
var form = event.target.form;
if (!form.checkValidity() && !form.hasAttribute('novalidate')) {
event.preventDefault();
var invalidElement = form.querySelector('[required]:invalid');
invalidElement.focus();
var createWarningElement = function () {
var invalidElementRect = invalidElement.getBoundingClientRect();
var warningElement = document.createElement('div');
warningElement.className = 'safariFormValidationWarningElement';
warningElement.innerHTML = 'this form field is invalid';
warningElement.style.top = (invalidElementRect.bottom + 7) + 'px';
warningElement.style.left = invalidElementRect.left + 'px';
document.body.appendChild(warningElement);
document.addEventListener('click', removeWarningElements, false);
document.addEventListener('keydown', removeWarningElements, false);
document.addEventListener('touchstart', removeWarningElements, false);
document.addEventListener('wheel', removeWarningElements, false);
return true;
};
window.setTimeout(createWarningElement, 200);
// 200ms usually give safari enough time to scroll to the .focus() element
}
return false;
};
var initalize = function () {
var submits = document.querySelectorAll('[type="submit"]');
for (var j = 0; j < submits.length; j++) {
var submit = submits[j];
submit.addEventListener('click', validateForm, true);
}
};
if (!Modernizr.formvalidation) {
if (document.readyState === 'loading' || document.readyState === 'interactive') {
window.addEventListener('load', initalize, true);
} else { initalize(); }
}
})(document, window, window.Modernizr);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment