/*
* jVal - dynamic jquery form field validation framework
* version 0.1.5
* Author: Jim Palmer
* Released under MIT license.
*/
(function($) {
// core jVal function - returns TRUE if all jVal validation passes, false if not
$.fn.jVal = function (options) {
$.fn.jVal.clean(this);
// clear jVal warnings
if ((options || '').toString().toUpperCase() == 'CLEAN')
return this; // chainable
$.fn.jVal.defaults = $.extend($.fn.jVal.defaults, options);
$(this).stop().find('.jfVal,.jValCover').stop().remove();
var passVal = true, dm = $.fn.jVal.defaults.message, ds = $.fn.jVal.defaults.style;
$(this).find('.jVal,[jVal]:not(:disabled):visible').each(
function () {
var cmd = $(this).data('jVal');
if ( typeof cmd !== 'object' ) eval( 'cmd = ' + ( $(this).data('jVal') || $(this).attr('jVal') ) + ';' );
//$.fn.jVal.clean(this);
if ( cmd instanceof Object && cmd.valid instanceof RegExp && !cmd.valid.test($(this).val()) ) {
$.fn.jVal.showWarning(cmd.target || this, cmd.message || dm, cmd.autoHide || false, cmd.styleType || ds);
passVal = false;
} else if ( cmd instanceof Object && cmd.valid instanceof Function ) {
var testFRet = cmd.valid( $(this).val(), this );
if ( testFRet === false || testFRet.length > 0 ) {
$.fn.jVal.showWarning(cmd.target || this, testFRet || cmd.message || dm, cmd.autoHide || false, cmd.styleType || ds);
passVal = false;
}
} else if ( ( cmd instanceof RegExp && !cmd.test($(this).val()) ) || ( cmd instanceof Function && !cmd($(this).val()) ) ) {
$.fn.jVal.showWarning(cmd.target || this, dm, cmd.autoHide || false, cmd.styleType || ds);
passVal = false;
}
}
);
return passVal;
};
// showWarning utility function
$.fn.jVal.showWarning = function (elements, message, autoHide, styleType) {
var par = $(elements).eq(0).parent();
clearTimeout( $(par).data('autoHide') ) && $(par).data('autoHide', null);
$.fn.jVal.clean(par);
$(elements).css({marginTop:'',position:'',borderColor:'#000000'});
var dbw = $.fn.jVal.defaults.border,
dp = $.fn.jVal.defaults.padding,
fieldWidth = 0, fieldHeight = 0,
absoluteLeft = $(elements).eq(0).position().left,
absoluteTop = $(elements).eq(0).position().top;
// normalize multi-element coordinates
$(elements).each(function () {
fieldWidth += $(this).outerWidth(true);
fieldHeight = Math.max( $(elements).outerHeight(true), fieldHeight );
absoluteLeft = Math.min( $(this).position().left, absoluteLeft );
absoluteTop = Math.min( $(this).position().top, absoluteTop );
});
var fwidth = 0, tPos = absoluteTop - dp - dbw, lPos = absoluteLeft + dp, rPos = absoluteLeft + fieldWidth + dp,
ph = (fieldHeight + (dp * 2)), fhp = fieldHeight + dp + dbw, fwp = fieldWidth + dp,
clips = [
'rect(0px, 5000px, ' + (dp + dbw) + 'px, 0px)', // top
'rect(' + fhp + 'px, 5000px, 5000px, 0px)', // bottom
'rect(' + dp + 'px, ' + dp + 'px, 5000px, 0px)', // left
'rect(' + dp + 'px, 5000px, 5000px, ' + fwp + 'px)']; // right
// fixed alerts, no wrapping
if (!$.fn.jVal.defaults.wrap) {
fieldWidth = ph = fph = 12;
rPos = lPos;
}
$(elements).eq(0).before(
'
' +
'' +
'
' +
'
' +
'' + message + '' +
'
' +
'
')
.parent().find('.jfVal>*').each(function () { fwidth += $(this).outerWidth() }).end()
.find('.jfVal').width(fwidth + 20);
for (var si = 1; si < 4; si++)
$(par).find('.jValSpacer:first').before(
$(par).find('.jValSpacer:first').clone().css({clip:clips[si]}) );
// autoHide = set spacer width + add autohide function to fx queue
if ( autoHide )
$(par).data( 'autoHide', setTimeout(function () { $(par).find('.jfVal').animate({left:lPos,opacity:0}, 200, function () { $.fn.jVal.clean(par); }); }, 2000) )
.find('.jfVal').css({'left':rPos});
else
$(par).find('.jfVal').css({opacity:0}).animate({left:rPos,opacity:1}, 200);
};
// validate key stroke
$.fn.jVal.valKey = function (keyRE, e, cF, cA) {
var ek = (typeof(e.keyCode) != 'undefined'), ec = (typeof(e.charCode) != 'undefined'),
k = e.keyCode, c = e.charCode, ks = k.toString();
// return if invalid regex
if ( !(keyRE instanceof RegExp) )
return false;
// test for ENTER key and cF being valid function otherwise return true
if ( /^13$/.test(String(k || c)) ) {
try { (this[cF]) ? this[cF](cA) : eval(cF); } catch(e) { return true; }
return -1;
}
// otherwise test for valid keys supported by the regex allowing meta keys by default
if ( e.ctrlKey || e.shiftKey || e.metaKey || (
ek && k > 0 && keyRE.test(String.fromCharCode(k)) ) ||
( ec && c > 0 && String.fromCharCode(c).search(keyRE) != (-1) ) ||
( ec && c != k && ek && ks.search(/^(8|9|45|46|35|36|37|39)$/) != (-1) ) ||
( ec && c == k && ek && ks.search(/^(8|9)$/) != (-1) ||
( !ec && ek && ks.search(/^(8|9|45|46|35|36|37|39)$/) != (-1) ) )
) {
return 1;
} else {
return 0;
}
};
// clear all displayed jVal warnings within scope
$.fn.jVal.clean = function (target) {
$(target)
.find('.jfVal,.jValSpacer').stop().remove().end()
.find('.jVal,[jVal]').css({position:'',borderColor:'',left:'0px',top:'0px'}).parent().find('.jValRelWrap').remove();
};
$.fn.jVal.init = function (options) {
$.fn.jVal.defaults = $.extend($.fn.jVal.defaults, options);
$('.jVal,[jVal]').filter(':not(:disabled)').unbind("blur").bind("blur", function (e) {
if ($.fn.jVal.defaults.blurCheck || $(this).hasClass('jValBlur'))
$(this).parent().jVal();
});
var keyFunc = function (e) {
eval( 'var cmd = ' + ( $(this).data('jValKey') || $(this).attr('jValKey') || $(this).data('jValKeyUp') || $(this).attr('jValKeyUp') ) + ';' );
var keyTest, ds = $.fn.jVal.defaults.style, dkm = $.fn.jVal.defaults.keyMessage,
autoHide = typeof(cmd.autoHide) != 'undefined' ? cmd.autoHide : true;
if ( cmd instanceof Object && cmd.valid instanceof Function ) {
keyTest = cmd.valid( e, this );
if ( keyTest === false || keyTest.length > 0 ) {
$.fn.jVal.clean(cmd.target || this);
// only show warning and allow keypress event to return true
$.fn.jVal.showWarning(cmd.target || this, ( keyTest || (cmd.message || dkm).replace('%c', String.fromCharCode(e.keyCode || e.charCode))), autoHide, cmd.styleType || ds);
} else
$.fn.jVal.clean($(cmd.target || this).parent());
} else {
keyTest = $.fn.jVal.valKey( ( (cmd instanceof Object) ? cmd.valid : cmd ), e, (cmd instanceof Object) ? cmd.cFunc : null, (cmd instanceof Object) ? cmd.cArgs : null );
if ( keyTest == 0 ) {
$.fn.jVal.clean(cmd.target || this);
$.fn.jVal.showWarning(cmd.target || this, (( cmd instanceof Object && cmd.message) || dkm).replace('%c', String.fromCharCode(e.keyCode || e.charCode)), autoHide, cmd.styleType || ds);
return false;
} else if ( keyTest == -1 )
return false;
else
$.fn.jVal.clean($(cmd.target || this).parent());
}
return true;
};
$('.jValKey,[jValKey]').filter(':not(:disabled)').unbind("keypress").bind("keypress", keyFunc);
$('.jValKeyUp,[jValKeyUp]').filter(':not(:disabled)').unbind("keyup").bind("keyup", keyFunc);
return this; // chainable
};
// jVal defaults
$.fn.jVal.defaults = {
blurCheck: false,
message: 'Invalid entry',
style: 'pod',
keyMessage: '"%c" Invalid character',
padding: 0,
border: 0,
wrap: true
};
// automatically init on dom load
$($.fn.jVal.init);
})(jQuery);