/**
* exValidation
*
* @version : 1.3.0
* @author : nori (norimania@gmail.com)
* @copyright : 5509 (http://5509.me/)
* @license : The MIT License
* @link : http://5509.me/log/exvalidation
* @modified : 2011-10-01 01:28
*/
;(function($, window, undefined) {
$.exValidationRules = $.exValidationRules || {};
var exValidation = function(form, conf) {
if ( form.length > 1 ) {
alert("You cannot select any forms");
return false;
}
this.form = form;
// for browse
var _this = this,
b = $("body");
conf = this.conf = $.extend({
errInsertPos : "body", // "body" or after(before)
err : null,
ok : null,
errFocus : false,
errHoverHide : false,
stepValidation : false,
scrollToErr : true,
scrollDuration : 500,
scrollAdjust : -10,
customScrollAdjust : false,
errPosition : "absolute", // fixed
errOpacity : undefined,
errTipPos : "right", // left
errTipCloseBtn : true,
errTipCloseLabel : "×",
errZIndex : 500,
errMsgPrefix : "\* ",
customAddError : null, // function(){}
customClearError : null, // function(){}
customSubmit : null, // function(){}
customListener : "blur keyup change focus",
customBind : null,
/* Using this conf, you can bind validation func to any element
{
object: $(button),
listener: "blur keyup change focus",
callback: function() {}
}
*/
customGetErrHeight : null,
firstValidate : false,
// default checking targets
inputs: [
"input:text",
"input:password",
"input:hidden",
"input:file",
"textarea",
"select",
"input[type=email]",
"input[type=url]",
"input[type=tel]",
"input[type=date]",
"input[type=datetime]",
"input[type=month]",
"input[type=week]",
"input[type=time]",
"input[type=datetime-local]",
"input[type=number]",
"input[type=range]",
"input[type=color]",
"[class*=group]",
"[class*=radio]",
"[class*=checkbox]"
],
// default checking targets in groups
groupInputs: [
"input:text",
"input:password",
"input:checkbox",
"input:radio",
"input[type=email]",
"input[type=url]",
"input[type=tel]",
"input[type=date]",
"input[type=datetime]",
"input[type=month]",
"input[type=week]",
"input[type=time]",
"input[type=datetime-local]",
"input[type=number]",
"input[type=range]",
"input[type=color]",
"select",
"textarea"
]
}, conf);
conf.inputs = conf.inputs.join(",");
conf.groupInputs = conf.groupInputs.join(",");
this.errFocus = function(id) {
if ( !conf.errFocus ) return false;
errFocus(id, conf.errZIndex);
};
this.errFocusClear = function() {
if ( !conf.errFocus ) return false;
errFocusClear(conf.errZIndex);
};
if ( fnConfirmation(conf.customSubmit) ) {
form.submit(function() {
return false;
});
}
$("input:checkbox,input:radio,input:button,input:submit,input:reset").click(function() {
_this.errFocusClear();
});
// addClasses for each inputs by validation rules
for ( var c in conf.rules ) {
$("#" + c).addClass(conf.rules[c]);
}
// If this form doesn"t have ID, formID for error tips is to be decided by random integer
var formID = form.attr("id")
? "form_" + form.attr("id")
: "form_" + randomInt()*randomInt();
var inputs = $(conf.inputs, form)
.filter(function() { return !$(this).parents().hasClass("chkgroup"); }),
classReg = returnReg(),
bindValidateFuncs = function(target, group) {
var self = group ? group : target;
target.bind(conf.customListener, function() {
_this.basicValidate(group ? group : this, conf.err, conf.ok);
_this.errFocus("#err_" + self.attr("id"));
}).blur(function() {
_this.errFocusClear();
});
};
inputs.each(function() {
var self = $(this),
cl = this.className,
id = this.id,
reg1 = undefined,
reg2 = undefined,
toggleTarget = undefined;
if ( conf.errTipPos === "right" ) {
self.addClass("errPosRight");
}
// if target has one of classRegulations
if ( classReg.test(cl) ) {
if ( conf.errInsertPos === "body" ) {
b.append(_this.generateErr(id, formID));
} else {
self[conf.errInsertPos](_this.generateErr(id, formID));
self.addClass(conf.errInsertPos);
}
if ( conf.errHoverHide ) {
$("#err_"+id).mouseenter(function() {
$(this).fadeOut();
});
}
//if ( conf.errTipCloseBtn ) {
// $("#err_"+id).append(
// $("")
// .addClass("formErrorClose")
// .text(conf.errTipCloseLabel)
// .click(function() {
// $(this).parent().fadeOut();
// })
// );
//}
if ( conf.errOpacity !== undefined ) {
$("#err_"+id).children().css("opacity", conf.errOpacity);
}
if ( conf.errPosition === "absolute" ) {
if ( fnConfirmation(conf.customGetErrHeight) ) {
_this.customGetErrHeight(id);
} else {
_this.getErrHeight(id, conf.errZIndex);
}
// Reget the position
$(window).resize(function() {
if ( fnConfirmation(conf.customGetErrHeight) ) {
_this.customGetErrHeight(id);
} else {
_this.getErrHeight(id, conf.errZIndex);
}
});
}
$("#err_"+id).hide();
}
});
// Checkboxによる分岐
inputs.each(function() {
var _self = $(this),
reg1 = undefined,
reg2 = undefined,
toggleTarget = undefined;
if ( this.className.match(/chktoggle_([^_]+)_([^ ]+)/) ) {
reg1 = "#" + RegExp.$1;
reg2 = "#" + RegExp.$2;
toggleTarget = $(reg2).removeClass("chkrequired");
$(reg1).click(function() {
console.log(toggleTarget);
if ( this.checked ) {
toggleTarget.addClass("chkrequired");
} else {
toggleTarget.removeClass("chkrequired");
}
_this.laterCall(toggleTarget);
});
}
if ( conf.firstValidate ) return;
if ( _self.hasClass("chkgroup") ) {
bindValidateFuncs($(conf.groupInputs, _self), _self);
} else {
bindValidateFuncs(_self);
}
});
// You call this func everytime you like after init
this.laterCall = function(t) {
_this.basicValidate(t, conf.err, conf.ok);
};
function _exeValidation(customBindCallback) {
if ( conf.firstValidate ) {
inputs.unbind("blur keyup change click");
conf.firstValidate = false;
}
inputs.each(function() {
var self = $(this);
_this.basicValidate(this, conf.err, conf.ok, true);
if ( self.hasClass("chkgroup") ) {
bindValidateFuncs($(conf.groupInputs, self), self);
} else {
bindValidateFuncs(self);
}
});
var err = $(".formError:visible[class*='"+formID+"']");
// if errs are displayed
if ( err.length > 0 ) {
if ( fnConfirmation(conf.customAddError) ) {
conf.customAddError();
}
if ( conf.scrollToErr ) {
var reverseOffsetTop,
infoErr, errTop,
scrollTarget = $.support.boxModel
? navigator.appName.indexOf("Opera") !== -1 ?
"html" : "html,body"
: "body";
if ( !conf.customScrollAdjust ) {
reverseOffsetTop = $(err[0]).offset().top;
errTop = $(err[0]);
for ( var i=0, l=err.length; i',
'',
'',
'',
''
].join("");
}else if(id == "c_select_companies"){
return [
''
].join("");
}else{
return [
''
].join("");
}
},
// Insert error message
insertErrMsg: function(t, id, c, errMsg) {
var msgs = $(".errMsg", "#err_"+id),
returnFlg = true;
if ( msgs.length > 0 ) {
$.each(msgs, function() {
if ( $(this).hasClass(c) ) {
returnFlg = false;
}
});
}
if ( !returnFlg ) return false;
$(".formErrorMsg", "#err_"+id).append(
$("")
.addClass("errMsg")
.addClass(c)
.text(errMsg)
);
this.getErrHeight(id);
},
// Basic get error height
getErrHeight: function(id, zIndex) {
if ( this.conf.errPosition !== "absolute" ) return false;
var input = $("#"+id),
err = $("#err_"+id),
target = input.is(":hidden") ? input.next() : input,
pos = target.offset();
if ( !!pos ) {
if(id == "c_select"){// 追加
var left = target.hasClass("errPosRight")
? pos.left + target.get(0).offsetWidth - 415
: pos.left - 20;
}else{
var left = target.hasClass("errPosRight")
? pos.left + target.get(0).offsetWidth - 40
: pos.left - 20;
}
err.css({
position: "absolute",
top: pos.top - err.get(0).offsetHeight,
left: left
});
}
if ( zIndex ) {
err.css("zIndex", zIndex);
}
},
// Basic validation
basicValidate: function(t, err, ok) {
var _t = $(t),
CL = _t.attr("class"),
chk = $.exValidationRules,
id = _t.attr("id"),
txt = "",
_this = this;
if ( _t.hasClass("chkgroup") ) {
var groupInputs = $(_this.conf.groupInputs, t);
groupInputs.each(function(i) {
var self = $(this);
txt += self.val();
if( CL.indexOf("chkemail") !== -1 && i==0 && self.val().length > 0 )
txt += "@";
});
} else {
txt = _t.val();
}
var check = {
isError: false,
failed: function(t, c) {
var msg = chk[c][0];
if ( c.match(/chkmin/i) && CL.match(/chkmin(\d+)/i) ) {
msg = RegExp.$1 + msg;
} else
if ( c.match(/chkmax/i) && CL.match(/chkmax(\d+)/i) ) {
msg = RegExp.$1 + msg;
}
if( fnConfirmation(err) ) {
err(t, id, _this.conf.errMsgPrefix + msg);
} else {
_t.addClass("err");
$("."+c, "#err_"+id).show();
$("#err_"+id).fadeIn();
_this.insertErrMsg(t, id, c, _this.conf.errMsgPrefix + msg);
_this.getErrHeight(id);
}
this.isError = true;
}
};
var c;
for ( c in chk ) {
if ( _t.hasClass(c)
|| (c === "chkmin" && CL.match(/(?:\s+|^)chkmin\d+(?:\s+|$)/) )
|| (c === "chkmax" && CL.match(/(?:\s+|^)chkmax\d+(?:\s+|$)/) )
|| ( CL.indexOf(c) !== -1 && CL.indexOf("chkretype") !== -1 ) ) {
if ( typeof(chk[c][1]) !== "function" ) {
if ( !txt.match(chk[c][1]) ) {
check.failed(t, c);
} else
if ( _this.conf.stepValidation ) {
if ( $(".errMsg:visible", "#err_"+id).length > 1 ) {
$("."+c, "#err_"+id).hide();
_this.getErrHeight(id);
}
}
} else {
if ( !chk[c][1](txt, t) ) {
check.failed(t, c);
} else
if ( _this.conf.stepValidation ) {
if ( $(".errMsg:visible", "#err_"+id).length > 1 ) {
$("."+c, "#err_"+id).hide();
_this.getErrHeight(id);
}
}
}
}
}
if ( !check.isError ) {
if ( fnConfirmation(ok) ) {
ok(t, id);
} else {
_t.removeClass("err");
$("#err_"+id).fadeOut();
}
}
}
}
// Common functions
function returnReg() {
var validationClasses = "";
for( var c in $.exValidationRules ) {
validationClasses += "(?:\\s+|^)"+c+"(?:\\s+|$)|";
}
validationClasses += "(?:\\s+|^)chkmin\\d+(?:\\s+|$)|";
validationClasses += "(?:\\s+|^)chkmax\\d+(?:\\s+|$)|";
validationClasses = validationClasses.replace(/\|$/,"");
return new RegExp(validationClasses);
}
function errFocusClear(errZIndex) {
$(".formError")
.removeClass("fadeOut")
.css("zIndex", errZIndex)
}
function errFocus(id, errZIndex) {
var formError = $(".formError");
formError.removeClass("fadeOut").css("zIndex", errZIndex);
formError.not(id).addClass("fadeOut");
$(id).css({
zIndex: errZIndex + 100
});
}
function fnConfirmation(fn) {
return fn && typeof fn === "function";
}
function randomInt() {
return Math.floor(Math.random()*10)+1;
}
// Extense the namespace of jQuery as method
// This function returns instance
$.fn.exValidation = function(options) {
return new exValidation(this, options);
};
if ( !$.fn.validation ) {
$.fn.validation = $.fn.exValidation;
}
})(jQuery, this);