/** * @author Andrew Dodson * @since 25th may 2007 * @since Oct 2011 (that's refreshing!) */ (function($){ "use strict"; // test for support $.support.datalist = (function(){ // El.list is available var el = document.createElement('input'); return typeof el.list !== 'undefined'; })(); $.support.placeholder = test('input[placeholder=wicked]'); $.support.range = test('input[type=range]'); $.support.number = test('input[type=number]'); $.support.date = test('input[type=date]'); // inputSupport function test(s){ var m = s.match(/^([a-z]+)(\[([a-z]+)(\=([a-z]+))?\])?$/i); try{ var test = document.createElement(m[1]); if(m[3]&&m[5]){ test[m[3]] = m[5]; //console.log(test[m[3]] +':'+ m[5]); return test[m[3]] === m[5]; } else if(m[3]){ return m[3] in test; } } catch(e){ return false; } return true; } /** * Basic Custom events for user interactions */ $(":input").live('keydown', function(e){ if(e.which===40){ $(this).trigger('down'); } if(e.which===38){ $(this).trigger('up'); } }); // the interval would be better if it was per input var interval; /** * CheckValidity * Our shim for which recreates the CheckValidity of HTML5 input's upon form submission */ function checkValidity(elem){ if (elem && 'checkValidity' in elem){ return elem.checkValidity(); } var $el = $(elem), m = { url : /^https?\:\/\/[a-z0-9]+/i, date : /^[0-9]{2,4}[\/\:\.\-][0-9]{2}[\/\:\.\-][0-9]{2,4}$/, time : /^[0-9]{2}\:[0-9]{2}(\:[0-9]{2})?$/, tel : /^\+?[0-9\s\.]{10,14}/, email : /^[a-z0-9\.\'\-]+@[a-z0-9\.\-]+$/i, number : /^-?[0-9]+(\.[0-9]+)?$/i, text : /.+/ }; // REQUIRED ATTRIBUTES var type = $el.attr('type'), min = $el.attr('min'), max = $el.attr('max'), step = $el.attr('step'), example = { url : "http://www.domain.com", time : "12:30", email : "name@domain.com", date : "2012-12-31" }[type], required= (!!$el.attr('required')), pattern = $el.attr('pattern'), value = (type === "checkbox" && !$el.prop('checked')) ? '' : (elem.value || elem.innerHTML), errorMsgs = { valueMissing : (type === "checkbox" ? "Please tick this box if you want to proceed" : "Value missing"), tooLong : "Too Long", typeMismatch : "Not a valid " + type + ( example ? " (e.g. " +example+ ")" : ''), patternMismatch : "Invalid pattern", rangeOverflow : "Value must be less than or equal to "+max, rangeUnderflow : "Value must be greater than or equal to "+min, stepMismatch : "Invalid value" }; // // Remove placeholder if($el.filter(".placeholder").attr('placeholder') === value){ value = ""; } elem.validity = { valueMissing : required&&value.length===0, tooLong : false, typeMismatch : (value.length>0)&&(type in m)&&!value.match( m[type] ), patternMismatch : pattern&&(value.length>0)&&!value.match( new RegExp('^'+pattern+'$') ), rangeOverflow : max && value.length && value > parseFloat(max), rangeUnderflow : min && value.length && value < parseFloat(min), stepMismatch : step && value.length && value%parseFloat(step), customError : false, valid : false // default }; // if this is a color? if(type==='color'&&value.length>0){ // does it work? var div = document.createElement("color"); try{ div.style.backgroundColor = value; } catch(e){} if( !div.style.backgroundColor ){ elem.validity.typeMismatch = true; } } // remove any previous error messages if($el.hasClass('invalid')){ $el .removeClass('invalid') .nextUntil(':input') .filter("div.errormsg") .remove(); } // Test each message for(var x in elem.validity){ if(elem.validity[x]){ $el .trigger('invalid') .addClass('invalid') // ADD CLASS .after('
'+errorMsgs[x]+'
'); setTimeout(function(){ $el .removeClass('invalid') .nextUntil(':input') .filter("div.errormsg") .fadeOut(); },10e3); return false; } } return (elem.validity.valid = true); }; // Check a form, or an individual value $.fn.checkValidity = function(){ var b = true; // AN HTML FORM WOULDN'T POST IF THERE ARE ERRORS. HOWEVER ($(this).is(':input') ? $(this) : $(":input", this)).each(function(){ if(b){ b = checkValidity(this); } }); return b; }, // Add form submit $('form').live('submit', function(e){ var b = $(this).checkValidity(); if(b){ // if this has passed lets remove placeholders $(":input.placeholder[placeholder]", this).val(""); } else{ // find the item in question and focus on it var $first = $('.invalid',this); if($first.length){ $first.get(0).focus(); } // prevent any further executions.. of course anything else could have been called. e.preventDefault(); e.stopPropagation(); } return b; }); // Add the oninput check $('input,textarea', 'form').live('input blur', function(e){ $(this) .removeClass('error') .next('div.error') .remove(); // clear away error markup because `it ugly`! if(interval){ clearTimeout(interval); } if(e.type==='blur'||e.type==='focusout'){ // check validity and provide information to user. $(this).checkValidity(); } else { var el = this; interval = setTimeout(function(){$(el).checkValidity();},3000); } }); // Placeholder support if(!$.support.placeholder){ /** * Hide/show the placeholder */ $(':input.placeholder[placeholder]', 'form').live('focus', function(e){ var method = (this.tagName==='INPUT'?'val':'text'); if($(this)[method]()===$(this).attr('placeholder')){ $(this)[method]("").removeClass('placeholder'); } }); $(':input[placeholder]', 'form').live('focusout', function(){ var method = (this.tagName==='INPUT'?'val':'text'); if($(this)[method]()===''){ $(this)[method]($(this).attr('placeholder')).addClass("placeholder"); } }); } /** * input[list=id] * Datalist provides a mechanism for suggesting values in an input field */ if(!$.support.datalist){ // Add keyup event to build the list based on user suggestions $('input[list]').live("keyup",function(e){ // Show $(this).addClass("datalist"); // $list var $list = $(this).nextUntil(":input").filter("div.datalist").eq(0); if($list.length===0){ $list = $("
").css({ position: 'absolute' }).insertAfter(this); } // dont change the list? if((e.which===38||e.which===40)&&$list.find("ul").length>0){ return; } // get the datalist var list = [], value = $(this).val().toLowerCase(); log("#" + $(this).attr("list")); $( "option", "#" + $(this).attr("list") ).each(function(){ var v = $(this).attr("value").toLowerCase(); log(v); if(v.indexOf(value)>-1){ list.push(v); } }); $list.empty(); $list.width($(this).width()); // AppendTo DOM $("