var FormCheck = new Class({ Implements: [Options, Events], options : { tipsClass : 'fc-tbx', errorClass : 'fc-error', fieldErrorClass : 'fc-field-error', submit : true, trimValue : false, validateDisabled : false, submitByAjax : false, ajaxResponseDiv : false, ajaxEvalScripts : false, onAjaxRequest : $empty, onAjaxSuccess : $empty, onAjaxFailure : $empty, onSubmit : $empty, onValidateSuccess : $empty, onValidateFailure : $empty, display : { showErrors : 0, titlesInsteadNames : 0, errorsLocation : 1, indicateErrors : 1, indicateErrorsInit : 0, keepFocusOnError : 0, checkValueIfEmpty : 1, addClassErrorToField : 0, removeClassErrorOnTipClosure : 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.", image : 'This field should only contain image types', phone : "Please enter a valid phone.", phone_inter : "Please enter a valid international phone number.", 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", words_min : "This field must concain at least %0 words, currently: %1 words", words_range : "This field must contain %0-%1 words, currently: %2 words", words_max : "This field must contain at max %0 words, currently: %1 words", 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-zA-Z0-9_\.\-\+%])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/, image : /.(jpg|jpeg|png|gif|bmp)$/i, phone : /^[\d\s ().-]+$/, phone_inter : /^\+{0,1}[0-9 \(\)\.\-]+$/, 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) { if (el.get('tag') == 'select' || el.get('tag') == 'input' || el.get('tag') == 'textarea') 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, position) { el.validation = []; el.getProperty("class").split(' ').each(function(classX) { if(classX.match(/^validate(\[.+\])$/)) { var valid = true; if (el.type == "radio") { this.validations.each(function(valider){ if (valider.name == el.name) valid = false;}, this)
}
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');}
}
if(validators[i].match(/^target:.+/)) { el.target = validators[i].match(/^target:(.+)/)[1];}
}
if (position && position <= this.validations.length) { var newValidations = []; this.validations.each(function(valider, i){ if (position == i+1 && valid) { newValidations.push(el); this.addListener(el);}
newValidations.push(valider);}, this); this.validations = newValidations;} else { if (valid) { this.validations.push(el); this.addListener(el);}
}
}
}, this);}, dispose : function(element) { this.validations.erase(element);}, addListener : function(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(/target:.+/)) return; 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 (ruleMethod == 'words') { if (this.validateWords(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) { var valueres = ( el.value.toInt() >= ruleArgs[0].toInt() ); msg = this.options.alerts.digitmin.replace("%0",ruleArgs[0]);} else { var valueres = ( el.value.toInt() >= ruleArgs[0].toInt() && el.value.toInt() <= ruleArgs[1].toInt() ); 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;}, validateWords: function(el,ruleArgs) { var min = ruleArgs[0]; var max = ruleArgs[1]; var words = el.value.replace(/[ \t\v\n\r\f\p]/m, ' ').replace(/[,.;:]/g, ' ').clean().split(' '); if(max == -1) { if(words.length < min) { el.errors.push(this.options.alerts.words_min.replace("%0", min).replace("%1", words.length)); return false;}
} else { if(min > 0) { if(words.length < min || words.length > max) { el.errors.push(this.options.alerts.words_range.replace("%0", min).replace("%1", max).replace("%2", words.length)); return false;}
} else { if(words.length > max) { el.errors.push(this.options.alerts.words_max.replace("%0", max).replace("%1", words.length)); return false;}
}
}
return true;}, isFormValid: function() { this.form.isValid = true; this.validations.each(function(el) { var validation = this.manageError(el,'testonly'); 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);}
}
window.fireEvent('resize');}, manageError : function(el, method) { var isValid = this.validate(el); if (method == 'testonly') return isValid; 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); 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))) { this.removeError(el); return true;}
return true;}, addError : function(obj) { var coord = obj.target ? $(obj.target).getCoordinates() : obj.getCoordinates(); if(!obj.element && this.options.display.indicateErrors != 0) { if (this.options.display.errorsLocation == 1) { var pos = (this.options.display.tipsPosition == 'left') ? coord.left : coord.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, 'tip');}.bind(this));}
obj.element.setStyle('top', coord.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(){ var coord = obj.target ? $(obj.target).getCoordinates() : obj.getCoordinates(); new Fx.Morph(obj.element, { 'duration' : this.options.display.fadeDuration
}).start({ 'left':[obj.element.getStyle('left'), coord.right + this.options.display.tipsOffsetX], 'top':[obj.element.getStyle('top'), coord.top - obj.element.getCoordinates().height + this.options.display.tipsOffsetY]
});}.bind(this);} else { obj.event = function(){ var coord = obj.target ? $(obj.target).getCoordinates() : obj.getCoordinates(); obj.element.setStyles({ 'left':coord.right + this.options.display.tipsOffsetX, 'top':coord.top - obj.element.getCoordinates().height + this.options.display.tipsOffsetY
});}.bind(this)
}
window.addEvent('resize', obj.event);}, removeError : function(obj, method) { if ((this.options.display.addClassErrorToField && !this.isChildType(obj) && this.options.display.removeClassErrorOnTipClosure) || (this.options.display.addClassErrorToField && !this.isChildType(obj) && !this.options.display.removeClassErrorOnTipClosure && method != 'tip'))
obj.removeClass(this.options.fieldErrorClass); if (!obj.element) return; 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);}
}, 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; if (obj.getProperty('type') != 'hidden') 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(forced) { this.validations.each(function(el) { if (el.element) { el.errors = []; el.isOK = true; if(this.options.display.flashTips == 1 || forced == 'forced') { 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.fireEvent('onSubmit'); 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();} else if(!this.options.submit) { new Event(event).stop();}
this.fireEvent('validateSuccess'); 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); this.fireEvent('validateFailure'); return false;}
}
}); 
