jQuery.webshims.register('form-native-extend', function($, webshims, window, doc, undefined, options){ "use strict"; var Modernizr = window.Modernizr; var modernizrInputTypes = Modernizr.inputtypes; if(!Modernizr.formvalidation || webshims.bugs.bustedValidity){return;} var typeModels = webshims.inputTypes; var validityRules = {}; webshims.addInputType = function(type, obj){ typeModels[type] = obj; }; webshims.addValidityRule = function(type, fn){ validityRules[type] = fn; }; webshims.addValidityRule('typeMismatch',function (input, val, cache, validityState){ if(val === ''){return false;} var ret = validityState.typeMismatch; if(!('type' in cache)){ cache.type = (input[0].getAttribute('type') || '').toLowerCase(); } if(typeModels[cache.type] && typeModels[cache.type].mismatch){ ret = typeModels[cache.type].mismatch(val, input); } return ret; }); var overrideNativeMessages = options.overrideMessages; var overrideValidity = (!modernizrInputTypes.number || !modernizrInputTypes.time || !modernizrInputTypes.range || overrideNativeMessages); var validityProps = ['customError','typeMismatch','rangeUnderflow','rangeOverflow','stepMismatch','tooLong','patternMismatch','valueMissing','valid']; var validityChanger = (overrideNativeMessages)? ['value', 'checked'] : ['value']; var validityElements = []; var testValidity = function(elem, init){ if(!elem){return;} var type = (elem.getAttribute && elem.getAttribute('type') || elem.type || '').toLowerCase(); if(!overrideNativeMessages && !typeModels[type]){ return; } if(overrideNativeMessages && !init && type == 'radio' && elem.name){ $(doc.getElementsByName( elem.name )).each(function(){ $.prop(this, 'validity'); }); } else { $.prop(elem, 'validity'); } }; var oldSetCustomValidity = {}; ['input', 'textarea', 'select'].forEach(function(name){ var desc = webshims.defineNodeNameProperty(name, 'setCustomValidity', { prop: { value: function(error){ error = error+''; var elem = (name == 'input') ? $(this).getNativeElement()[0] : this; desc.prop._supvalue.call(elem, error); if(webshims.bugs.validationMessage){ webshims.data(elem, 'customvalidationMessage', error); } if(overrideValidity){ webshims.data(elem, 'hasCustomError', !!(error)); testValidity(elem); } } } }); oldSetCustomValidity[name] = desc.prop._supvalue; }); if(overrideValidity || overrideNativeMessages){ validityChanger.push('min'); validityChanger.push('max'); validityChanger.push('step'); validityElements.push('input'); } if(overrideNativeMessages){ validityChanger.push('required'); validityChanger.push('pattern'); validityElements.push('select'); validityElements.push('textarea'); } if(overrideValidity){ var stopValidity; validityElements.forEach(function(nodeName){ var oldDesc = webshims.defineNodeNameProperty(nodeName, 'validity', { prop: { get: function(){ if(stopValidity){return;} var elem = (nodeName == 'input') ? $(this).getNativeElement()[0] : this; var validity = oldDesc.prop._supget.call(elem); if(!validity){ return validity; } var validityState = {}; validityProps.forEach(function(prop){ validityState[prop] = validity[prop]; }); if( !$.prop(elem, 'willValidate') ){ return validityState; } stopValidity = true; var jElm = $(elem), cache = {type: (elem.getAttribute && elem.getAttribute('type') || '').toLowerCase(), nodeName: (elem.nodeName || '').toLowerCase()}, val = jElm.val(), customError = !!(webshims.data(elem, 'hasCustomError')), setCustomMessage ; stopValidity = false; validityState.customError = customError; if( validityState.valid && validityState.customError ){ validityState.valid = false; } else if(!validityState.valid) { var allFalse = true; $.each(validityState, function(name, prop){ if(prop){ allFalse = false; return false; } }); if(allFalse){ validityState.valid = true; } } $.each(validityRules, function(rule, fn){ validityState[rule] = fn(jElm, val, cache, validityState); if( validityState[rule] && (validityState.valid || !setCustomMessage) && (overrideNativeMessages || (typeModels[cache.type] && typeModels[cache.type].mismatch)) ) { oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, rule)); validityState.valid = false; setCustomMessage = true; } }); if(validityState.valid){ oldSetCustomValidity[nodeName].call(elem, ''); webshims.data(elem, 'hasCustomError', false); } else if(overrideNativeMessages && !setCustomMessage && !customError){ $.each(validityState, function(name, prop){ if(name !== 'valid' && prop){ oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name)); return false; } }); } return validityState; }, writeable: false } }); }); validityChanger.forEach(function(prop){ webshims.onNodeNamesPropertyModify(validityElements, prop, function(s){ testValidity(this); }); }); if(doc.addEventListener){ var inputThrottle; var testPassValidity = function(e){ if(!('form' in e.target)){return;} var form = e.target.form; clearTimeout(inputThrottle); testValidity(e.target); if(form && overrideNativeMessages){ $('input', form).each(function(){ if(this.type == 'password'){ testValidity(this); } }); } }; doc.addEventListener('change', testPassValidity, true); if(overrideNativeMessages){ doc.addEventListener('blur', testPassValidity, true); doc.addEventListener('keydown', function(e){ if(e.keyCode != 13){return;} testPassValidity(e); }, true); } doc.addEventListener('input', function(e){ clearTimeout(inputThrottle); inputThrottle = setTimeout(function(){ testValidity(e.target); }, 290); }, true); } var validityElementsSel = validityElements.join(','); webshims.addReady(function(context, elem){ $(validityElementsSel, context).add(elem.filter(validityElementsSel)).each(function(){ $.prop(this, 'validity'); }); }); if(overrideNativeMessages){ webshims.ready('DOM form-message', function(){ webshims.activeLang({ register: 'form-core', callback: function(){ $('input, select, textarea') .getNativeElement() .each(function(){ if(webshims.data(this, 'hasCustomError')){return;} var elem = this; var validity = $.prop(elem, 'validity') || {valid: true}; var nodeName; if(validity.valid){return;} nodeName = (elem.nodeName || '').toLowerCase(); $.each(validity, function(name, prop){ if(name !== 'valid' && prop){ oldSetCustomValidity[nodeName].call(elem, webshims.createValidationMessage(elem, name)); return false; } }); }) ; } }); }); } } //end: overrideValidity webshims.defineNodeNameProperty('input', 'type', { prop: { get: function(){ var elem = this; var type = (elem.getAttribute('type') || '').toLowerCase(); return (webshims.inputTypes[type]) ? type : elem.type; } } }); });