var FormCheck = new Class({ Implements: [Options, Events], options : { tipsClass: 'fc-tbx', errorClass: 'fc-error', fieldErrorClass: 'fc-field-error', trimValue : false, validateDisabled : false, submitByAjax : false, ajaxResponseDiv : false, ajaxEvalScripts : false, onAjaxRequest : $empty, onAjaxSuccess : $empty, onAjaxFailure : $empty, display : { showErrors : 0, titlesInsteadNames : 0, errorsLocation : 1, indicateErrors : 1, indicateErrorsInit : 0, keepFocusOnError : 0, checkValueIfEmpty : 1, addClassErrorToField : 0, fixPngForIe : 1, replaceTipsEffect : 1, flashTips : 0, closeTipsButton : 1, tipsPosition : "right", tipsOffsetX : -45, tipsOffsetY : 0, listErrorsAtTop : false, scrollToFirst : true, fadeDuration : 300
}, alerts : { required: "This field is required.", alpha: "This field accepts alphabetic characters only.", alphanum: "This field accepts alphanumeric characters only.", nodigit: "No digits are accepted.", digit: "Please enter a valid integer.", digitltd: "The value must be between %0 and %1", number: "Please enter a valid number.", email: "Please enter a valid email.", phone: "Please enter a valid phone.", url: "Please enter a valid url.", confirm: "This field is different from %0", differs: "This value must be different of %0", length_str: "The length is incorrect, it must be between %0 and %1", length_fix: "The length is incorrect, it must be exactly %0 characters", lengthmax: "The length is incorrect, it must be at max %0", lengthmin: "The length is incorrect, it must be at least %0", checkbox: "Please check the box", radios: "Please select a radio", select: "Please choose a value"
}, regexp : { required : /[^.*]/, alpha : /^[a-z ._-]+$/i, alphanum : /^[a-z0-9 ._-]+$/i, digit : /^[-+]?[0-9]+$/, nodigit : /^[^0-9]+$/, number : /^[-+]?\d*\.?\d+$/, email : /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i, phone : /^[\d\s ().-]+$/, url : /^(http|https|ftp)\:\/\/[a-z0-9\-\.]+\.[a-z]{2,3}(:[a-z0-9]*)?\/?([a-z0-9\-\._\?\,\'\/\\\+&amp;%\$#\=~])*$/i
}
}, initialize : function(form, options) { if (this.form = $(form)) { this.form.isValid = true; this.regex = ['length']; this.setOptions(options); if (typeof(formcheckLanguage) != 'undefined') this.options.alerts = $merge(this.options.alerts, formcheckLanguage); this.validations = []; this.alreadyIndicated = false; this.firstError = false; var regex = new Hash(this.options.regexp); regex.each(function(el, key) { this.regex.push(key);}, this); this.form.getElements("*[class*=validate]").each(function(el) { this.register(el);}, this); this.form.addEvents({ "submit": this.onSubmit.bind(this)
}); if(this.options.display.fixPngForIe) this.fixIeStuffs(); document.addEvent('mousewheel', function(){ this.isScrolling = false;}.bind(this));}
}, register : function(el) { el.validation = []; el.getProperty("class").split(' ').each(function(classX) { if(classX.match(/^validate(\[.+\])$/)) { var validators = eval(classX.match(/^validate(\[.+\])$/)[1]); for(var i = 0; i < validators.length; i++) { el.validation.push(validators[i]); if (validators[i].match(/^confirm\[/)) { var field = eval(validators[i].match(/^.+(\[.+\])$/)[1].replace(/([A-Z0-9\._-]+)/i, "'$1'")); if (this.form[field].validation.contains('required')){ el.validation.push('required');}
}
}
this.addListener(el);}
}, this);}, dispose : function(element) { this.validations.erase(element);}, addListener : function(el) { this.validations.push(el); el.errors = []; if (this.options.display.indicateErrorsInit) { this.validations.each(function(el) { if(!this.manageError(el,'submit')) this.form.isValid = false;}, this); return true;}
if (el.validation[0] == 'submit') { el.addEvent('click', function(e){ if (this.onSubmit(e)) this.form.submit();}.bind(this)); return true;}
if (this.isChildType(el) == false) el.addEvent('blur', function() { (function(){ if(!this.fxRunning && (el.element || this.options.display.showErrors == 1) && (this.options.display.checkValueIfEmpty || el.value))
this.manageError(el, 'blur')
}.bind(this)).delay(100);}.bind(this))
else if (this.isChildType(el) == true) { var nlButtonGroup = this.form.getElements('input[name="'+ el.getProperty("name") +'"]'); nlButtonGroup.each(function(radio){ radio.addEvent('blur', function(){ (function(){ if((el.element || this.options.display.showErrors == 1) && (this.options.display.checkValueIfEmpty || el.value)) this.manageError(el, 'click');}.bind(this)).delay(100);}.bind(this))
},this);}
}, validate : function(el) { el.errors = []; el.isOk = true; if (!this.options.validateDisabled && el.get('disabled')) return true; if (this.options.trimValue && el.value) el.value = el.value.trim(); el.validation.each(function(rule) { if(this.isChildType(el)) { if (this.validateGroup(el) == false) { el.isOk = false;}
} else { var ruleArgs = []; if(rule.match(/^.+\[/)) { var ruleMethod = rule.split('[')[0]; ruleArgs = eval(rule.match(/^.+(\[.+\])$/)[1].replace(/([A-Z0-9\._-]+)/i, "'$1'"));} else var ruleMethod = rule; if (this.regex.contains(ruleMethod) && el.get('tag') != "select") { if (this.validateRegex(el, ruleMethod, ruleArgs) == false) { el.isOk = false;}
}
if (ruleMethod == 'confirm') { if (this.validateConfirm(el, ruleArgs) == false) { el.isOk = false;}
}
if (ruleMethod == 'differs') { if (this.validateDiffers(el, ruleArgs) == false) { el.isOk = false;}
}
if (el.get('tag') == "select" || (el.type == "checkbox" && ruleMethod == 'required')) { if (this.simpleValidate(el) == false) { el.isOk = false;}
}
if(rule.match(/%[A-Z0-9\._-]+$/i) || (el.isOk && rule.match(/~[A-Z0-9\._-]+$/i))) { if(eval(rule.slice(1)+'(el)') == false) { el.isOk = false;}
}
}
}, this); if (el.isOk) return true; else return false;}, simpleValidate : function(el) { if (el.get('tag') == 'select' && el.selectedIndex <= 0) { el.errors.push(this.options.alerts.select); return false;} else if (el.type == "checkbox" && el.checked == false) { el.errors.push(this.options.alerts.checkbox); return false;}
return true;}, validateRegex : function(el, ruleMethod, ruleArgs) { var msg = ""; if (ruleArgs[1] && ruleMethod == 'length') { if (ruleArgs[1] == -1) { this.options.regexp.length = new RegExp("^[\\s\\S]{"+ ruleArgs[0] +",}$"); msg = this.options.alerts.lengthmin.replace("%0",ruleArgs[0]);} else if(ruleArgs[0] == ruleArgs[1]) { this.options.regexp.length = new RegExp("^[\\s\\S]{"+ ruleArgs[0] +"}$"); msg = this.options.alerts.length_fix.replace("%0",ruleArgs[0]);} else { this.options.regexp.length = new RegExp("^[\\s\\S]{"+ ruleArgs[0] +","+ ruleArgs[1] +"}$"); msg = this.options.alerts.length_str.replace("%0",ruleArgs[0]).replace("%1",ruleArgs[1]);}
} else if (ruleArgs[0] && ruleMethod == 'length') { this.options.regexp.length = new RegExp("^.{0,"+ ruleArgs[0] +"}$"); msg = this.options.alerts.lengthmax.replace("%0",ruleArgs[0]);} else { msg = this.options.alerts[ruleMethod];}
if (ruleArgs[1] && ruleMethod == 'digit') { var regres = true; if (!this.options.regexp.digit.test(el.value)) { el.errors.push(this.options.alerts[ruleMethod]); regres = false;}
if (ruleArgs[1] == -1) { if (el.value >= ruleArgs[0]) var valueres = true; else var valueres = false; msg = this.options.alerts.digitmin.replace("%0",ruleArgs[0]);} else { if (el.value >= ruleArgs[0] && el.value <= ruleArgs[1]) var valueres = true; else var valueres = false; msg = this.options.alerts.digitltd.replace("%0",ruleArgs[0]).replace("%1",ruleArgs[1]);}
if (regres == false || valueres == false) { el.errors.push(msg); return false;}
} else if (this.options.regexp[ruleMethod].test(el.value) == false) { el.errors.push(msg); return false;}
return true;}, validateConfirm: function(el,ruleArgs) { var confirm = ruleArgs[0]; if(el.value != this.form[confirm].value){ if (this.options.display.titlesInsteadNames)
var msg = this.options.alerts.confirm.replace("%0",this.form[confirm].getProperty('title')); else
var msg = this.options.alerts.confirm.replace("%0",confirm); el.errors.push(msg); return false;}
return true;}, validateDiffers: function(el,ruleArgs) { var differs = ruleArgs[0]; if(el.value == this.form[differs].value){ if (this.options.display.titlesInsteadNames)
var msg = this.options.alerts.differs.replace("%0",this.form[differs].getProperty('title')); else
var msg = this.options.alerts.differs.replace("%0",differs); el.errors.push(msg); return false;}
return true;}, isFormValid: function() { this.form.isValid = true; this.validations.each(function(el) { var validation = this.manageError(el,'submit'); if(!validation) this.form.isValid = false;}, this); return this.form.isValid;}, isChildType: function(el) { return ($defined(el.type) && el.type == 'radio') ? true : false;}, validateGroup : function(el) { el.errors = []; var nlButtonGroup = this.form[el.getProperty("name")]; el.group = nlButtonGroup; var cbCheckeds = false; for(var i = 0; i < nlButtonGroup.length; i++) { if(nlButtonGroup[i].checked) { cbCheckeds = true;}
}
if(cbCheckeds == false) { el.errors.push(this.options.alerts.radios); return false;} else { return true;}
}, listErrorsAtTop : function(obj) { if(!this.form.element) { this.form.element = new Element('div', {'id' : 'errorlist', 'class' : this.options.errorClass}).injectTop(this.form);}
if ($type(obj) == 'collection') { new Element('p').set('html',"<span>" + obj[0].name + " : </span>" + obj[0].errors[0]).injectInside(this.form.element);} else { if ((obj.validation.contains('required') && obj.errors.length > 0) || (obj.errors.length > 0 && obj.value && obj.validation.contains('required') == false)) { obj.errors.each(function(error) { new Element('p').set('html',"<span>" + obj.name + " : </span>" + error).injectInside(this.form.element);}, this);}
}
}, manageError : function(el, method) { var isValid = this.validate(el); if ((!isValid && el.validation.flatten()[0].contains('confirm[')) || (!isValid && el.validation.contains('required')) || (!el.validation.contains('required') && el.value && !isValid)) { if(this.options.display.listErrorsAtTop == true && method == 'submit')
this.listErrorsAtTop(el, method); if (this.options.display.indicateErrors == 2 ||this.alreadyIndicated == false || el.name == this.alreadyIndicated.name)
{ if(!this.firstError) this.firstError = el; this.alreadyIndicated = el; if (this.options.display.keepFocusOnError && el.name == this.firstError.name) (function(){el.focus()}).delay(20); this.addError(el); return false;}
} else if ((isValid || (!el.validation.contains('required') && !el.value)) && el.element) { this.removeError(el); return true;}
return true;}, addError : function(obj) { if(!obj.element && this.options.display.indicateErrors != 0) { if (this.options.display.errorsLocation == 1) { var pos = (this.options.display.tipsPosition == 'left') ? obj.getCoordinates().left : obj.getCoordinates().right; var options = { 'opacity' : 0, 'position' : 'absolute', 'float' : 'left', 'left' : pos + this.options.display.tipsOffsetX
}
obj.element = new Element('div', {'class' : this.options.tipsClass, 'styles' : options}).injectInside(document.body); this.addPositionEvent(obj);} else if (this.options.display.errorsLocation == 2){ obj.element = new Element('div', {'class' : this.options.errorClass, 'styles' : {'opacity' : 0}}).injectBefore(obj);} else if (this.options.display.errorsLocation == 3){ obj.element = new Element('div', {'class' : this.options.errorClass, 'styles' : {'opacity' : 0}}); if ($type(obj.group) == 'object' || $type(obj.group) == 'collection')
obj.element.injectAfter(obj.group[obj.group.length-1]); else
obj.element.injectAfter(obj);}
}
if (obj.element && obj.element != true) { obj.element.empty(); if (this.options.display.errorsLocation == 1) { var errors = []; obj.errors.each(function(error) { errors.push(new Element('p').set('html', error));}); var tips = this.makeTips(errors).injectInside(obj.element); if(this.options.display.closeTipsButton) { tips.getElements('a.close').addEvent('mouseup', function(){ this.removeError(obj);}.bind(this));}
obj.element.setStyle('top', obj.getCoordinates().top - tips.getCoordinates().height + this.options.display.tipsOffsetY);} else { obj.errors.each(function(error) { new Element('p').set('html',error).injectInside(obj.element);});}
if (!this.options.display.fadeDuration || Browser.Engine.trident && Browser.Engine.version == 5 && this.options.display.errorsLocation < 2) { obj.element.setStyle('opacity', 1);} else { obj.fx = new Fx.Tween(obj.element, { 'duration' : this.options.display.fadeDuration, 'ignore' : true, 'onStart' : function(){ this.fxRunning = true;}.bind(this), 'onComplete' : function() { this.fxRunning = false; if (obj.element && obj.element.getStyle('opacity').toInt() == 0) { obj.element.destroy(); obj.element = false;}
}.bind(this)
})
if(obj.element.getStyle('opacity').toInt() != 1) obj.fx.start('opacity', 1);}
}
if (this.options.display.addClassErrorToField && this.isChildType(obj) == false){ obj.addClass(this.options.fieldErrorClass); obj.element = obj.element || true;}
}, addPositionEvent : function(obj) { if(this.options.display.replaceTipsEffect) { obj.event = function(){ new Fx.Morph(obj.element, { 'duration' : this.options.display.fadeDuration
}).start({ 'left':[obj.element.getStyle('left'), obj.getCoordinates().right + this.options.display.tipsOffsetX], 'top':[obj.element.getStyle('top'), obj.getCoordinates().top - obj.element.getCoordinates().height + this.options.display.tipsOffsetY]
});}.bind(this);} else { obj.event = function(){ obj.element.setStyles({ 'left':obj.getCoordinates().right + this.options.display.tipsOffsetX, 'top':obj.getCoordinates().top - obj.element.getCoordinates().height + this.options.display.tipsOffsetY
});}.bind(this)
}
window.addEvent('resize', obj.event);}, removeError : function(obj) { this.alreadyIndicated = false; obj.errors = []; obj.isOK = true; window.removeEvent('resize', obj.event); if (this.options.display.errorsLocation >= 2 && obj.element) { new Fx.Tween(obj.element, { 'duration': this.options.display.fadeDuration
}).start('height', 0);}
if (!this.options.display.fadeDuration || Browser.Engine.trident && Browser.Engine.version == 5 && this.options.display.errorsLocation == 1 && obj.element) { this.fxRunning = true; obj.element.destroy(); obj.element = false; (function(){this.fxRunning = false}.bind(this)).delay(200);} else if (obj.element && obj.element != true) { obj.fx.start('opacity', 0);}
if (this.options.display.addClassErrorToField && !this.isChildType(obj))
obj.removeClass(this.options.fieldErrorClass);}, focusOnError : function (obj) { if (this.options.display.scrollToFirst && !this.alreadyFocused && !this.isScrolling) { if (!this.options.display.indicateErrors || !this.options.display.errorsLocation) { var dest = obj.getCoordinates().top-30;} else if (this.alreadyIndicated.element) { switch (this.options.display.errorsLocation){ case 1 :
var dest = obj.element.getCoordinates().top; break; case 2 :
var dest = obj.element.getCoordinates().top-30; break; case 3 :
var dest = obj.getCoordinates().top-30; break;}
this.isScrolling = true;}
if (window.getScroll.y != dest) { new Fx.Scroll(window, { onComplete : function() { this.isScrolling = false; obj.focus();}.bind(this)
}).start(0,dest);} else { this.isScrolling = false; obj.focus();}
this.alreadyFocused = true;}
}, fixIeStuffs : function () { if (Browser.Engine.trident4) { var rpng = new RegExp('url\\(([\.a-zA-Z0-9_/:-]+\.png)\\)'); var search = new RegExp('(.+)formcheck\.css'); for (var i = 0; i < document.styleSheets.length; i++){ if (document.styleSheets[i].href.match(/formcheck\.css$/)) { var root = document.styleSheets[i].href.replace(search, '$1'); var count = document.styleSheets[i].rules.length; for (var j = 0; j < count; j++){ var cssstyle = document.styleSheets[i].rules[j].style; var bgimage = root + cssstyle.backgroundImage.replace(rpng, '$1'); if (bgimage && bgimage.match(/\.png/i)){ var scale = (cssstyle.backgroundRepeat == 'no-repeat') ? 'crop' : 'scale'; cssstyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=\'' + bgimage + '\', sizingMethod=\''+ scale +'\')'; cssstyle.backgroundImage = "none";}
}
}
}
}
}, makeTips : function(txt) { var table = new Element('table'); table.cellPadding ='0'; table.cellSpacing ='0'; table.border ='0'; var tbody = new Element('tbody').injectInside(table); var tr1 = new Element('tr').injectInside(tbody); new Element('td', {'class' : 'tl'}).injectInside(tr1); new Element('td', {'class' : 't'}).injectInside(tr1); new Element('td', {'class' : 'tr'}).injectInside(tr1); var tr2 = new Element('tr').injectInside(tbody); new Element('td', {'class' : 'l'}).injectInside(tr2); var cont = new Element('td', {'class' : 'c'}).injectInside(tr2); var errors = new Element('div', {'class' : 'err'}).injectInside(cont); txt.each(function(error) { error.injectInside(errors);}); if (this.options.display.closeTipsButton) new Element('a',{'class' : 'close'}).injectInside(cont); new Element('td', {'class' : 'r'}).injectInside(tr2); var tr3 = new Element('tr').injectInside(tbody); new Element('td', {'class' : 'bl'}).injectInside(tr3); new Element('td', {'class' : 'b'}).injectInside(tr3); new Element('td', {'class' : 'br'}).injectInside(tr3); return table;}, reinitialize: function() { this.validations.each(function(el) { if (el.element) { el.errors = []; el.isOK = true; if(this.options.display.flashTips == 1) { el.element.destroy(); el.element = false;}
}
}, this); if (this.form.element) this.form.element.empty(); this.alreadyFocused = false; this.firstError = false; this.elementToRemove = this.alreadyIndicated; this.alreadyIndicated = false; this.form.isValid = true;}, submitByAjax: function() { var url = this.form.getProperty('action'); this.fireEvent('ajaxRequest'); new Request({ url: url, method: this.form.getProperty('method'), data : this.form.toQueryString(), evalScripts: this.options.ajaxEvalScripts, onFailure: function(instance){ this.fireEvent('ajaxFailure', instance);}.bind(this), onSuccess: function(result){ this.fireEvent('ajaxSuccess', result); if(this.options.ajaxResponseDiv) $(this.options.ajaxResponseDiv).set('html',result);}.bind(this)
}).send();}, onSubmit: function(event) { this.reinitialize(); this.validations.each(function(el) { var validation = this.manageError(el,'submit'); if(!validation) this.form.isValid = false;}, this); if (this.form.isValid) { if (this.options.submitByAjax) { new Event(event).stop(); this.submitByAjax();}
return true;} else { new Event(event).stop(); if (this.elementToRemove && this.elementToRemove != this.firstError && this.options.display.indicateErrors == 1) { this.removeError(this.elementToRemove);}
this.focusOnError(this.firstError); return false;}
}
}); 
